608 lines
19 KiB
C++
608 lines
19 KiB
C++
#include "sckUrban.h"
|
|
|
|
uint8_t pot_6_db_preset[] = {0, 7, 26, 96, 255};
|
|
uint8_t pot_7_db_preset[] = {0, 17, 97, 255, 255};
|
|
|
|
void SckUrban::setup() {
|
|
|
|
// Gases
|
|
gasSetup(SENSOR_CO);
|
|
gasSetup(SENSOR_NO2);
|
|
|
|
// Sound
|
|
ADCini();
|
|
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV16; // clock prescaler to 16
|
|
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1024 | // 1024 samples for averaging
|
|
ADC_AVGCTRL_ADJRES(0x4ul); // Adjusting result by 4
|
|
gainChange(0);
|
|
};
|
|
|
|
float SckUrban::getReading(SensorType wichSensor) {
|
|
|
|
switch (wichSensor) {
|
|
case SENSOR_NOISE: return getNoise(); break;
|
|
case SENSOR_HUMIDITY: return getHumidity(); break;
|
|
case SENSOR_TEMPERATURE: return getTemperature(); break;
|
|
case SENSOR_LIGHT: return getLight(); break;
|
|
case SENSOR_CO: return gasRead(SENSOR_CO); break;
|
|
case SENSOR_CO_HEAT_TIME: return gasHeatingTime(SENSOR_CO); break;
|
|
case SENSOR_CO_HEAT_CURRENT: return gasGetHeaterCurrent(SENSOR_CO); break;
|
|
case SENSOR_CO_HEAT_SUPPLY_VOLTAGE: return gasGetRegulatorVoltage(SENSOR_CO); break;
|
|
case SENSOR_CO_HEAT_DROP_VOLTAGE: return (SENSOR_CO); break;
|
|
case SENSOR_CO_LOAD_RESISTANCE: return gasGetLoadResistance(SENSOR_CO); break;
|
|
case SENSOR_NO2: return gasRead(SENSOR_NO2); break;
|
|
case SENSOR_NO2_HEAT_TIME: return gasHeatingTime(SENSOR_NO2); break;
|
|
case SENSOR_NO2_HEAT_CURRENT: return gasGetHeaterCurrent(SENSOR_NO2); break;
|
|
case SENSOR_NO2_HEAT_SUPPLY_VOLTAGE: return gasGetRegulatorVoltage(SENSOR_NO2); break;
|
|
case SENSOR_NO2_HEAT_DROP_VOLTAGE: return (SENSOR_NO2); break;
|
|
case SENSOR_NO2_LOAD_RESISTANCE: return gasGetLoadResistance(SENSOR_NO2); break;
|
|
}
|
|
}
|
|
|
|
String SckUrban::control(SensorType wichSensor, String command) {
|
|
switch (wichSensor) {
|
|
case SENSOR_NO2:
|
|
case SENSOR_CO: {
|
|
|
|
if (command.startsWith("set on")) {
|
|
gasOn(wichSensor);
|
|
return F("Starting sensor...");
|
|
|
|
} else if (command.startsWith("set off")) {
|
|
gasOff(wichSensor);
|
|
return F("Shuting off heater...");
|
|
|
|
} else if (command.startsWith("set current")) {
|
|
command.replace("set current", "");
|
|
command.trim();
|
|
int wichValue = command.toInt();
|
|
gasHeat(wichSensor, wichValue);
|
|
return String F("Setting current to: ") + String(wichValue) + F(" mA\n\rActual value: ") + String(gasGetHeaterCurrent(wichSensor)) + F(" mA");
|
|
|
|
} else if (command.startsWith("set voltage")) {
|
|
command.replace("set voltage", "");
|
|
command.trim();
|
|
int wichValue = command.toInt();
|
|
gasSetRegulatorVoltage(wichSensor, wichValue);
|
|
return String F("Setting heater voltage to: ") + String(wichValue) + F(" mV\n\rActual value: ") + String(gasGetRegulatorVoltage(wichSensor)) + F(" mV");
|
|
|
|
} else if (command.startsWith("correct current")) {
|
|
gasCorrectHeaterCurrent(wichSensor);
|
|
return String F("Actual value: ") + String(gasGetHeaterCurrent(wichSensor)) + F(" mA\n\rCorrecting current\n\rActual value: ") + String(gasGetHeaterCurrent(wichSensor)) + F(" mA");
|
|
|
|
} else if (command.startsWith("help")) {
|
|
return F("Available commands for this sensor:\n\r* set on - set off\n\r* set current\n\r* set voltage");
|
|
|
|
} else {
|
|
return F("Unrecognized command!! please try again...");
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Noise sensor
|
|
float SckUrban::getNoise() {
|
|
uint16_t soundraw = 0;
|
|
// uint8_t section = 0;
|
|
boolean validReading = 0;
|
|
|
|
while (!validReading) {
|
|
switch (gain_step) {
|
|
case 0:
|
|
soundraw = analogRead(S4);
|
|
if (soundraw <= 600) // primer intervalo 0~66, gain=max=76dB
|
|
{
|
|
sounddB = 12.5f * log10f(getsound()) + 33;
|
|
validReading = 1;
|
|
}
|
|
else gainChange(1);
|
|
break;
|
|
case 1:
|
|
soundraw = analogRead(S4);
|
|
if ((soundraw >= 15) & (soundraw <= 400)) // segundo intervalo 66~85, gain=34dB
|
|
{
|
|
sounddB = 12.5f * log10f(getsound()) + 53.5;
|
|
validReading = 1;
|
|
}
|
|
else if (soundraw < 15) gainChange(0);
|
|
else if (soundraw > 400) gainChange(2);
|
|
break;
|
|
case 2:
|
|
soundraw = analogRead(S4);
|
|
if ((soundraw >= 20) & (soundraw <= 120)) // tercer intervalo 85~95, gain=17dB
|
|
{
|
|
sounddB = 12.5f * log10f(getsound()) + 69.5;
|
|
validReading = 1;
|
|
}
|
|
else if (soundraw < 20) gainChange(1);
|
|
else if (soundraw > 120) gainChange(3);
|
|
break;
|
|
case 3:
|
|
soundraw = analogRead(S4);
|
|
if ((soundraw >= 20) & (soundraw <= 120)) // cuarto intervalo 95~105, gain=8dB
|
|
{
|
|
sounddB = 12.5f * log10f(getsound()) + 79;
|
|
validReading = 1;
|
|
}
|
|
else if (soundraw < 20) gainChange(2);
|
|
else if (soundraw > 120) gainChange(4);
|
|
break;
|
|
case 4:
|
|
soundraw = analogRead(S4);
|
|
if ((soundraw >= 82) & (soundraw <= 400)) // quinto intervalo 105~final, gain=min=5dB
|
|
{
|
|
sounddB = 13.5f * log10f(getsound()) + 79.5;
|
|
validReading = 1;
|
|
}
|
|
else if (soundraw < 82) gainChange(3);
|
|
else if (soundraw > 400) {
|
|
sounddB = 13.5f * log10f(getsound()) + 79.5; // espacio no comprobado
|
|
validReading = 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return sounddB;
|
|
}
|
|
|
|
void SckUrban::gainChange(uint8_t value) {
|
|
writeResistorRaw(6, pot_6_db_preset[value]);
|
|
//delay(20);
|
|
writeResistorRaw(7, pot_7_db_preset[value]);
|
|
if (gain_step < value) delay(250); // la carga del condensador que filtra la señal rectificada es inmediata, la descarga no
|
|
// por lo que si aumentamos la ganancia el voltaje sera mayor y no hemos de esperar tanto, si
|
|
// disminuimos la ganancia hemos de esperar mas a que el condensador se descargue
|
|
// value = 0 G = 76dB
|
|
// value = 1 G = 34dB
|
|
// value = 2 G = 17dB
|
|
// value = 3 G = 8dB
|
|
// value = 4 G = 5.8dB
|
|
gain_step = value;
|
|
}
|
|
|
|
float SckUrban::getsound() {
|
|
|
|
return ((float)(analogRead(S4)) + 1) / RESOLUTION_ANALOG * VCC;
|
|
}
|
|
|
|
void SckUrban::writeResistorRaw(byte resistor, int value) {
|
|
|
|
if (value>255) value = 0;
|
|
else if (value<0) value = 255;
|
|
|
|
byte POT = POT1;
|
|
byte ADDR = resistor;
|
|
|
|
if ((resistor==6)||(resistor==7))
|
|
{
|
|
POT = POT4;
|
|
ADDR = resistor - 6;
|
|
}
|
|
writeI2C(POT, 16, 192); // select WR (volatile) registers in POT
|
|
writeI2C(POT, ADDR, value);
|
|
}
|
|
|
|
void SckUrban::writeI2C(byte deviceaddress, byte address, byte data ) {
|
|
Wire.beginTransmission(deviceaddress);
|
|
Wire.write(address);
|
|
Wire.write(data);
|
|
Wire.endTransmission();
|
|
delay(4);
|
|
}
|
|
|
|
byte SckUrban::readI2C(int deviceaddress, byte address ) {
|
|
byte data = 0x0000;
|
|
Wire.beginTransmission(deviceaddress);
|
|
Wire.write(address);
|
|
Wire.endTransmission();
|
|
Wire.requestFrom(deviceaddress,1);
|
|
unsigned long time = millis();
|
|
while (!Wire.available()) if ((millis() - time)>500) return 0x00;
|
|
data = Wire.read();
|
|
return data;
|
|
}
|
|
|
|
// Temperature sensor
|
|
uint16_t SckUrban::readSHT(uint8_t type){
|
|
uint16_t DATA = 0;
|
|
Wire.beginTransmission(SHT21_I2C_DIR);
|
|
Wire.write(type);
|
|
Wire.endTransmission();
|
|
Wire.requestFrom(SHT21_I2C_DIR,3);
|
|
unsigned long time = millis();
|
|
while (!Wire.available()) if ((millis() - time)>500) return 0x00;
|
|
DATA = Wire.read()<<8;
|
|
DATA += Wire.read();
|
|
Wire.read();
|
|
DATA &= ~0x0003;
|
|
return DATA;
|
|
}
|
|
|
|
float SckUrban::getHumidity() {
|
|
|
|
return (-6 + (125*(readSHT(0xE5)/65536.0)));
|
|
}
|
|
|
|
float SckUrban::getTemperature() {
|
|
|
|
return (-46.85 + (175.72*(readSHT(0xE3)/65536.0)));
|
|
}
|
|
|
|
float SckUrban::getLight() {
|
|
|
|
uint8_t TIME0 = 0xDA;
|
|
uint8_t GAIN0 = 0x00;
|
|
uint8_t DATA [8] = {0x03, TIME0, 0x00 ,0x00, 0x00, 0xFF, 0xFF ,GAIN0} ;
|
|
|
|
uint16_t DATA0 = 0;
|
|
uint16_t DATA1 = 0;
|
|
|
|
Wire.beginTransmission(BH1730_I2C_DIR);
|
|
Wire.write(0x80|0x00);
|
|
for(int i= 0; i<8; i++) Wire.write(DATA[i]);
|
|
Wire.endTransmission();
|
|
delay(100);
|
|
Wire.beginTransmission(BH1730_I2C_DIR);
|
|
Wire.write(0x94);
|
|
Wire.endTransmission();
|
|
Wire.requestFrom(BH1730_I2C_DIR, 4);
|
|
DATA0 = Wire.read();
|
|
DATA0=DATA0|(Wire.read()<<8);
|
|
DATA1 = Wire.read();
|
|
DATA1=DATA1|(Wire.read()<<8);
|
|
|
|
uint8_t Gain = 0x00;
|
|
if (GAIN0 == 0x00) Gain = 1;
|
|
else if (GAIN0 == 0x01) Gain = 2;
|
|
else if (GAIN0 == 0x02) Gain = 64;
|
|
else if (GAIN0 == 0x03) Gain = 128;
|
|
|
|
float ITIME = (256- TIME0)*2.7;
|
|
|
|
float Lx = 0;
|
|
float cons = (Gain * 100) / ITIME;
|
|
float comp = (float)DATA1/DATA0;
|
|
|
|
|
|
if (comp<0.26) Lx = ( 1.290*DATA0 - 2.733*DATA1 ) / cons;
|
|
else if (comp < 0.55) Lx = ( 0.795*DATA0 - 0.859*DATA1 ) / cons;
|
|
else if (comp < 1.09) Lx = ( 0.510*DATA0 - 0.345*DATA1 ) / cons;
|
|
else if (comp < 2.13) Lx = ( 0.276*DATA0 - 0.130*DATA1 ) / cons;
|
|
else Lx=0;
|
|
|
|
return Lx;
|
|
}
|
|
|
|
// Gas sensors
|
|
void SckUrban::gasSetup(SensorType wichSensor) {
|
|
|
|
if (wichSensor == SENSOR_CO) {
|
|
// Voltage regulator setup
|
|
pinMode(SHUTDOWN_CONTROL_REGULATOR_CO_SENSOR_HEATER_PIN, OUTPUT);
|
|
digitalWrite(SHUTDOWN_CONTROL_REGULATOR_CO_SENSOR_HEATER_PIN, LOW); // Turn off regulator
|
|
|
|
// Load resistor setup (minimal safe value is 820)
|
|
setPot(POT_CO_LOAD_RESISTOR, 50000);
|
|
gasCOheaterState = false;
|
|
|
|
} else if (wichSensor == SENSOR_NO2) {
|
|
|
|
// Voltage regulator setup
|
|
pinMode(SHUTDOWN_CONTROL_REGULATOR_NO2_SENSOR_HEATER_PIN, OUTPUT);
|
|
digitalWrite(SHUTDOWN_CONTROL_REGULATOR_NO2_SENSOR_HEATER_PIN, LOW); // Turn off regulator
|
|
|
|
// Load resistor setup (minimal safe value is 820)
|
|
setPot(POT_NO2_LOAD_RESISTOR, 50000);
|
|
gasNO2heaterState = false;
|
|
}
|
|
}
|
|
|
|
void SckUrban::gasOn(SensorType wichSensor) {
|
|
|
|
if (wichSensor == SENSOR_CO) {
|
|
|
|
// Load resistor setup (minimal safe value is 820)
|
|
setPot(POT_CO_LOAD_RESISTOR, 100000);
|
|
|
|
gasHeat(wichSensor, CO_HEATING_CURRENT);
|
|
// TODO do i need to correct current here???
|
|
|
|
} else if (wichSensor == SENSOR_NO2) {
|
|
|
|
// Load resistor setup (minimal safe value is 820)
|
|
setPot(POT_NO2_LOAD_RESISTOR, 100000);
|
|
|
|
gasHeat(wichSensor, NO2_HEATING_CURRENT);
|
|
}
|
|
}
|
|
|
|
void SckUrban::gasOff(SensorType wichSensor) {
|
|
|
|
if (wichSensor == SENSOR_CO) {
|
|
// Turn off regulator
|
|
digitalWrite(SHUTDOWN_CONTROL_REGULATOR_CO_SENSOR_HEATER_PIN, LOW);
|
|
|
|
// Load resistor setup (minimal safe value is 820)
|
|
setPot(POT_CO_LOAD_RESISTOR, 100000);
|
|
|
|
gasCOheaterState = false;
|
|
|
|
} else if (wichSensor == SENSOR_NO2) {
|
|
// Turn off regulator
|
|
digitalWrite(SHUTDOWN_CONTROL_REGULATOR_NO2_SENSOR_HEATER_PIN, LOW);
|
|
|
|
// Load resistor setup (minimal safe value is 820)
|
|
setPot(POT_NO2_LOAD_RESISTOR, 100000);
|
|
|
|
gasNO2heaterState = false;
|
|
}
|
|
}
|
|
|
|
void SckUrban::gasHeat(SensorType wichSensor, uint32_t wichCurrent) {
|
|
|
|
if (wichSensor == SENSOR_CO) {
|
|
|
|
// store requested current
|
|
// TODO Save this current in eprom for persistence
|
|
CO_HEATING_CURRENT = wichCurrent;
|
|
|
|
// Calculate required voltage for requested current
|
|
uint32_t calculatedRegulatorVoltage = (CO_HEATER_RESISTANCE * CO_HEATING_CURRENT) + (CO_HEATER_RESISTOR * CO_HEATING_CURRENT);
|
|
|
|
// Start on the low side and wait for current correction
|
|
calculatedRegulatorVoltage -= 500;
|
|
|
|
// Set voltage to functional value
|
|
gasSetRegulatorVoltage(wichSensor, calculatedRegulatorVoltage);
|
|
|
|
// Turn on regulator
|
|
digitalWrite(SHUTDOWN_CONTROL_REGULATOR_CO_SENSOR_HEATER_PIN, HIGH);
|
|
|
|
startHeaterTime_CO = millis();
|
|
gasCOheaterState = true;
|
|
|
|
// Correct current
|
|
gasCorrectHeaterCurrent(wichSensor);
|
|
|
|
} else if (wichSensor == SENSOR_NO2) {
|
|
|
|
// store requested current
|
|
// Save this current in eprom for persistence
|
|
NO2_HEATING_CURRENT = wichCurrent;
|
|
|
|
// Calculate required voltage for requested current
|
|
uint32_t calculatedRegulatorVoltage = (NO2_HEATER_RESISTANCE * NO2_HEATING_CURRENT) + (NO2_HEATER_RESISTOR * NO2_HEATING_CURRENT);
|
|
|
|
// Start on the low side and wait for current correction
|
|
calculatedRegulatorVoltage -= 500;
|
|
|
|
// Set voltage to functional value
|
|
gasSetRegulatorVoltage(wichSensor, calculatedRegulatorVoltage);
|
|
|
|
// Turn on regulator
|
|
digitalWrite(SHUTDOWN_CONTROL_REGULATOR_NO2_SENSOR_HEATER_PIN, HIGH);
|
|
|
|
startHeaterTime_NO2 = millis();
|
|
gasNO2heaterState = true;
|
|
|
|
// Correct current
|
|
gasCorrectHeaterCurrent(wichSensor);
|
|
}
|
|
}
|
|
|
|
float SckUrban::gasGetRegulatorVoltage(SensorType wichSensor) {
|
|
|
|
// Get actual variable resistor value (for selected sensor)
|
|
uint32_t actualPOTvalue = 0;
|
|
if (wichSensor == SENSOR_CO) actualPOTvalue = getPot(POT_CO_REGULATOR);
|
|
else if (wichSensor == SENSOR_NO2) actualPOTvalue = getPot(POT_NO2_REGULATOR);
|
|
|
|
// Calculate actual regulator voltage TODO check calculation
|
|
float regulatorVoltage = (((float)actualPOTvalue / HEATER_REGULATOR_RESISTOR) + 1) * 800.0;
|
|
|
|
return regulatorVoltage;
|
|
}
|
|
|
|
float SckUrban::gasGetDropVoltage(SensorType wichSensor) {
|
|
if (wichSensor == SENSOR_CO) return ((float)average(CO_HEATER_VOLTAGE_PIN) * VCC) / RESOLUTION_ANALOG; // (mV) Measure voltage
|
|
else if (wichSensor == SENSOR_NO2) return ((float)average(NO2_HEATER_VOLTAGE_PIN) * VCC) / RESOLUTION_ANALOG; // (mV) Measure voltage
|
|
}
|
|
|
|
void SckUrban::gasSetRegulatorVoltage(SensorType wichSensor, uint32_t wichVoltage) {
|
|
|
|
// each step is around 13 mV
|
|
|
|
// Minimal value (800 mV)
|
|
if (wichVoltage < 800) wichVoltage = 800;
|
|
|
|
// Calculate required variable resistor for desired voltage
|
|
float desiredPOTvalue = ((wichVoltage / 800.0) - 1) * HEATER_REGULATOR_RESISTOR;
|
|
|
|
// Set new variable resistor value
|
|
if (wichSensor == SENSOR_CO) {
|
|
setPot(POT_CO_REGULATOR, (uint32_t)desiredPOTvalue);
|
|
} else if (wichSensor == SENSOR_NO2) {
|
|
setPot(POT_NO2_REGULATOR, (uint32_t)desiredPOTvalue);
|
|
}
|
|
}
|
|
|
|
float SckUrban::gasGetHeaterCurrent(SensorType wichSensor) {
|
|
float measuredVoltage = gasGetDropVoltage(wichSensor);
|
|
if (wichSensor == SENSOR_CO) return measuredVoltage / CO_HEATER_RESISTOR; // (mA) Calculates current
|
|
else if (wichSensor == SENSOR_NO2) return measuredVoltage / NO2_HEATER_RESISTOR; // (mA) Calculates current
|
|
}
|
|
|
|
void SckUrban::gasCorrectHeaterCurrent(SensorType wichSensor) {
|
|
|
|
// New current value depends on sensor
|
|
float desiredCurrent = 0;
|
|
if (wichSensor == SENSOR_CO) desiredCurrent = CO_HEATING_CURRENT;
|
|
else if (wichSensor == SENSOR_NO2) desiredCurrent = NO2_HEATING_CURRENT;
|
|
|
|
// HeaterCurrent = HeaterVoltage / HEATER_RESISTOR
|
|
float heaterVoltage = gasGetDropVoltage(wichSensor); // (mV) Measure voltage
|
|
float heaterCurrent = 0;
|
|
if (wichSensor == SENSOR_CO) heaterCurrent = heaterVoltage / CO_HEATER_RESISTOR; // (mA) Calculates current
|
|
else if (wichSensor == SENSOR_NO2) heaterCurrent = heaterVoltage / NO2_HEATER_RESISTOR; // (mA) Calculates current
|
|
|
|
while (desiredCurrent - heaterCurrent > 0) {
|
|
|
|
// HeaterCurrent = HeaterVoltage / HEATER_RESISTOR
|
|
heaterVoltage = gasGetDropVoltage(wichSensor); // (mV) Measure voltage
|
|
if (wichSensor == SENSOR_CO) heaterCurrent = heaterVoltage / CO_HEATER_RESISTOR; // (mA) Calculates current
|
|
else if (wichSensor == SENSOR_NO2) heaterCurrent = heaterVoltage / NO2_HEATER_RESISTOR; // (mA) Calculates current
|
|
|
|
// HeaterResistance = (RegulatorVoltage - HeaterVoltage) / HeaterCurrent;
|
|
float regulatorVoltage = gasGetRegulatorVoltage(wichSensor);
|
|
float heaterResistance = (regulatorVoltage - heaterVoltage) / heaterCurrent; // (Ohms)
|
|
|
|
// RegulatorVoltage = HeaterCurrent * (HeaterResistance + HEATER_RESISTOR)
|
|
float newRegulatorVoltage = 0;
|
|
if (wichSensor == SENSOR_CO) newRegulatorVoltage = desiredCurrent * (heaterResistance + CO_HEATER_RESISTOR); // Calculates new voltage for desired current
|
|
else if (wichSensor == SENSOR_NO2) newRegulatorVoltage = desiredCurrent * (heaterResistance + NO2_HEATER_RESISTOR); // Calculates new voltage for desired current
|
|
|
|
// Increase at least one step of the regulator POT (one step is +/- 13 mV)
|
|
if (newRegulatorVoltage - regulatorVoltage < 20) newRegulatorVoltage += 20;
|
|
|
|
gasSetRegulatorVoltage(wichSensor, newRegulatorVoltage); // Sets calculated voltage
|
|
|
|
heaterCurrent = gasGetHeaterCurrent(wichSensor);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
float SckUrban::gasGetSensorResistance(SensorType wichSensor) {
|
|
|
|
float sensorVoltage = 0;
|
|
|
|
if (wichSensor == SENSOR_CO) sensorVoltage = ((float)average(CO_SENSOR_VOLTAGE_PIN) * VCC) / RESOLUTION_ANALOG; // (mV) Measure sensor Voltage
|
|
else if (wichSensor == SENSOR_NO2) sensorVoltage = ((float)average(NO2_SENSOR_VOLTAGE_PIN) * VCC) / RESOLUTION_ANALOG; // (mV) Measure sensor Voltage
|
|
|
|
if (sensorVoltage > VCC) sensorVoltage = VCC;
|
|
float sensorResistance = ((VCC - sensorVoltage) / sensorVoltage) * gasGetLoadResistance(wichSensor); // (Ohms) calculate sensor resistance
|
|
|
|
return sensorResistance;
|
|
}
|
|
|
|
uint32_t SckUrban::gasHeatingTime(SensorType wichSensor) {
|
|
|
|
if (wichSensor == SENSOR_CO && gasCOheaterState) {
|
|
|
|
return (millis() - startHeaterTime_CO) / 1000;
|
|
|
|
} else if (wichSensor == SENSOR_NO2 && gasNO2heaterState) {
|
|
|
|
return (millis() - startHeaterTime_NO2) / 1000;
|
|
|
|
// If the sensors are off
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
uint32_t SckUrban::gasGetLoadResistance(SensorType wichSensor) {
|
|
if (wichSensor == SENSOR_CO) return getPot(POT_CO_LOAD_RESISTOR);
|
|
else if (wichSensor == SENSOR_NO2) return getPot(POT_NO2_LOAD_RESISTOR);
|
|
}
|
|
|
|
float SckUrban::gasRead(SensorType wichSensor) {
|
|
|
|
// Turn on heater if it isn't
|
|
if (wichSensor == SENSOR_CO && !gasCOheaterState) gasHeat(SENSOR_CO, CO_HEATING_CURRENT);
|
|
else if (wichSensor == SENSOR_NO2 && !gasNO2heaterState) gasHeat(SENSOR_NO2, NO2_HEATING_CURRENT);
|
|
|
|
Resistor wichResistor;
|
|
if (wichSensor == SENSOR_CO) {
|
|
wichResistor.deviceAddress = POT_CO_LOAD_RESISTOR.deviceAddress;
|
|
wichResistor.resistorAddress = POT_CO_LOAD_RESISTOR.resistorAddress;
|
|
} else if (wichSensor == SENSOR_NO2) {
|
|
wichResistor.deviceAddress = POT_NO2_LOAD_RESISTOR.deviceAddress;
|
|
wichResistor.resistorAddress = POT_NO2_LOAD_RESISTOR.resistorAddress;
|
|
}
|
|
|
|
// Get value from both resistors
|
|
float loadResistor = getPot(wichResistor); // (Ohms)
|
|
float sensorResistance = gasGetSensorResistance(wichSensor); // (Ohms)
|
|
|
|
// Adjust range max 5 times
|
|
uint8_t cycles = 5;
|
|
for (uint8_t i=0; i<cycles; ++i) {
|
|
if (abs(loadResistor - sensorResistance) > 1000) { // If difference between result and POT load resistor is graeter than 1000, try to improve resolution
|
|
if (sensorResistance < 2000) setPot(wichResistor, 2000); // Set POT to minimal value in 2000
|
|
else if (sensorResistance > 100000) {
|
|
setPot(wichResistor, 100000); // Set POT to maximum value
|
|
break; // Dont keep going if result resitance is greater than max POT value
|
|
}
|
|
else setPot(wichResistor, sensorResistance); // Set POT to the same value as the result
|
|
delay(10);
|
|
|
|
loadResistor = getPot(wichResistor);
|
|
sensorResistance = gasGetSensorResistance(wichSensor);
|
|
|
|
} else break;
|
|
}
|
|
return sensorResistance / 1000;
|
|
}
|
|
|
|
|
|
// Utility functions
|
|
void SckUrban::ADCini() {
|
|
byte temp = readI2C(ADC_DIR,0)&B00000000;
|
|
writeI2C(ADC_DIR, 0, temp);
|
|
}
|
|
|
|
void SckUrban::ADCoff() {
|
|
byte temp = readI2C(ADC_DIR,0)&B00000000;
|
|
writeI2C(ADC_DIR, 0, temp);
|
|
}
|
|
|
|
void SckUrban::setPot(Resistor wichPot, uint32_t value) {
|
|
|
|
// Check minimal safe value for Gas sensor (820)
|
|
if (wichPot.deviceAddress == POT3 && value < 820) value = 820;
|
|
|
|
// Data to be writen
|
|
int data=0x00;
|
|
if (value>100000) value = 100000;
|
|
data = (int)(value/ohmsPerStep);
|
|
|
|
Wire.beginTransmission(wichPot.deviceAddress);
|
|
Wire.write(wichPot.resistorAddress);
|
|
Wire.write(data);
|
|
Wire.endTransmission();
|
|
delay(4);
|
|
}
|
|
|
|
uint32_t SckUrban::getPot(Resistor wichPot) {
|
|
|
|
byte data = 0x0000;
|
|
|
|
Wire.beginTransmission(wichPot.deviceAddress);
|
|
Wire.write(wichPot.resistorAddress);
|
|
Wire.endTransmission();
|
|
Wire.requestFrom(wichPot.deviceAddress,1);
|
|
|
|
// Wait for answer with a timeout
|
|
uint16_t waitTimeout = 500;
|
|
uint32_t time = millis();
|
|
while (!Wire.available()) if ((millis() - time) > waitTimeout) return 0x00;
|
|
data = Wire.read();
|
|
return data*ohmsPerStep;
|
|
}
|
|
|
|
float SckUrban::average(uint8_t wichPin) {
|
|
|
|
uint32_t numReadings = 100;
|
|
long total = 0;
|
|
float average = 0;
|
|
for(uint32_t i=0; i<numReadings; i++) {
|
|
total = total + analogRead(wichPin);
|
|
}
|
|
average = (float)total / numReadings;
|
|
return average;
|
|
}
|