2.2 Part Two: The Temperature and Water Level Sensors
The next part of the project is to add the thermistor and water level sensor. First, start with the thermistor since it is more difficult to implement than the water level sensor.
As previously mentioned, the thermistor is part of a voltage divider system as shown in Figure 1-3. The output of the divider circuit is connected to an ADC input. Once the ADC reads and performs the ADC conversion, the conversion result is then used as part of the Simplified β (beta) Parameter equation (see Equation 2-2), which is a derivative of the Steinhart-Hart equation. The Simplified β Parameter equation uses terms that are easily attainable, such as the thermistor resistance value at 25°C, and reduces the complexity of the calculations that software must perform. To further simplify the software calculations, several of the more math-intensive variables have been pre-calculated by hand and listed as software constants.
These calculations require floating-point math, similar to the pH sensor. When the project is created for this part of the system, the same steps to change from the C99 standard to the C90 standard must be followed. This will allow the use of 24-bit floats, which can then be broken down into three individual bytes for I2C transmission (see Part One: The pH Sensor for details).
Converting the Thermistor Input into Temperature shows the code used to calculate the temperature value and convert the 24-bit floating-point variable into three individual bytes. The snippet includes variables that have been precalculated in an effort to save additional memory space.
Converting the Thermistor Input into Temperature
uint16_t adc_result = 0; float temperature = 0.00000; float T0 = 0.00335; // 1 / 298.15 float B = 0.00025; // 1 / 3950 (beta value) #define MAXADC 1023.000 // 10-Bit ADCC #define K 273.1500 // Kelvin constant #define LN 0.4343 // Log(e) while (1) { adc_result = ADC_GetConversion(channel_ANA2); temperature = (MAXADC / (float)adc_result) - 1.00000;// R equiv of voltage temperature = log10(temperature); // Take Log of the temperature temperature = temperature / LN; // Divide log(temp) by Log(e) value temperature = B * temperature; // Multiply by B constant temperature += T0; // Add T0 constant temperature = 1 / temperature; // Invert to get degrees in Kelvin (K) temperature -= K; // Subtract K constant //printf("%1.2fC \r\n", temperature); // Display temp (uint24_t)thermCopy = (float)temperature * 100; // Break down the float variable into 3 bytes to transmit thermLowByte = thermCopy & 0xFF; // Get low byte thermHighByte = (thermCopy >> 8) & 0xFF; // Get high byte thermUpperByte = (thermCopy >> 16) & 0xFF; // Get upper byte (uint8_t)i2cArray[0] = (uint8_t)thermLowByte; (uint8_t)i2cArray[1] = (uint16_t)thermHighByte; (uint8_t)i2cArray[2] = (uint24_t)thermUpperByte; }
Once the temperature has been calculated, the water level sensor can be added. The water level sensor is very easy to implement. Since the ADC is already in use, another ADC input can be enabled to read the sensor output. The water level sensor is a “normally open” circuit, meaning that no current can flow. When the water level is low, magnetic forces from the floating part of the sensor are close enough to force the two metals contacts located in the shaft of the sensor to make contact. This allows current to flow through the sensor, which results in a voltage that can be read by the ADC.
Two wires protrude from the shaft of the water level sensor. One wire is connected to a power source; in this case, it is connected to VDD. The other end is connected to an ADC input pin. To prevent any transients from damaging the ADC input, a 100 Ω resistor is added in series to the ADC input. When the sensor is connected and the water level is good, the ADC pin will be floating and the ADC readings will be random. However, when the circuit closes, VDD appears on the ADC pin. Software can read the input, and if the ADC value is anything below VDD, the water level can be determined as good. If the ADC value is equal to VDD, the water level is too low.
Water Level Sensor Calculation shows the routine used to determine the water level. Since the sensor output can be converted into a 10-bit result, it is easy to convert the 10-bit reading into two bytes for I2C transmission.
Water Level Sensor Calculation
lvlSensor = ADC_GetConversion(channel_ANA4); lvlSnsLowByte = lvlSensor & 0xFF; lvlSnsHighByte = (lvlSensor >> 8) & 0xFF; (uint8_t)i2cArray[3] = (uint8_t)lvlSnsLowByte; (uint8_t)i2cArray[4] = (uint8_t)lvlSnsHighByte; //printf("%d ADC Value \r\n", lvlSensor);
The last step is to add the I2C slave drivers. The same driver set as used in Part One can be used here as well.