Adding new sensors
This page explains how to modify the code to add new sensors
The data collection from the sensors is limited to the address on i2c, which is from 0 – 127, this can lead to conflict if some sensors have the same address. Most sensors have the possibility to change the address by putting some pins high or low.
Adding new sensors
To add a new sensor to the system, start of by creating a new function to collect data from that sensor. The function must collect data from the sensor thru I2c or thru use of an analog connector. The system has three i2c connectors and one analog port. It is possible to connect sensor inside the node box and directly connect it thru the i2c multiplexer. In the original design the analog port, and two i2c ports are already in use. This can be modified.
Creating a new sensor data function
Step 1:
Create an int32_t variable for the sensor, if it is a sensor with multiple values then create an array. (note: this system is limited to negative and positive values, it is not supported with floats, this can be implimented, see sending code.)
int32_t sensor_value_bh1750;
int32_t multispecter_sensor_value[10];
Step 2:
Create a function that fills the variable or array with the value from sensor. (Some sensors require some time after being activated, before it collects data.) note: if the sensor requires calibration make sure the function returns the sensor value after calibrated.
//function for the light sensor
void lightsensor_BH1750()
{
lightMeter.begin();
delay(500);
uint16_t lux = lightMeter.readLightLevel();
sensor_value_bh1750 = lux;
}
//function for the multispecter sensor
void multispecter_as7341()
{
if (as7341.begin())
{
as7341.setATIME(100); // integrator time
as7341.setASTEP(999); // integrator time
as7341.setGain(AS7341_GAIN_128X); //gain, x0.5, x1,x2, x4, x8, x18, x32, x64, x128, x256, x512
multispecter_sensor_value[0] = as7341.getChannel(AS7341_CHANNEL_415nm_F1); //F1(405-425nm
multispecter_sensor_value[1] = as7341.getChannel(AS7341_CHANNEL_445nm_F2); //F2(435-455nm
multispecter_sensor_value[2] = as7341.getChannel(AS7341_CHANNEL_480nm_F3); //F3(470-490nm
multispecter_sensor_value[3] = as7341.getChannel(AS7341_CHANNEL_515nm_F4); //F4(505-525nm
multispecter_sensor_value[4] = as7341.getChannel(AS7341_CHANNEL_555nm_F5); //F5(545-565nm
multispecter_sensor_value[5] = as7341.getChannel(AS7341_CHANNEL_590nm_F6); //F6(580-600nm
multispecter_sensor_value[6] = as7341.getChannel(AS7341_CHANNEL_630nm_F7); //F7(620-640nm
multispecter_sensor_value[7] = as7341.getChannel(AS7341_CHANNEL_680nm_F8); //F8(670-690nm
multispecter_sensor_value[8] = as7341.getChannel(AS7341_CHANNEL_CLEAR); // Clear
multispecter_sensor_value[9] = as7341.getChannel(AS7341_CHANNEL_NIR); // NIR
}
if (!as7341.readAllChannels())
{
Serial.println("Error reading all channels!");
}
}
Step 3:
Create a new case in the function fill_data_array()
with the sensor address.
case 0x23: //lightsensor BH1750.
lightsensor_BH1750();
sensor_array[2] = sensor_value_bh1750;
break;
case 0x39: //multispecter sensor AS7341.
for (int i = 0; i < 2; i++) // has to go thru a loop to collect data.
{
multispecter_as7341(); //fills the array with new values.
for (int i = 0; i < 11; i++)
{
sensor_array[i + 2] = multispecter_sensor_value[i];
}
}
break;
Now the sensor is added into the data collection part of the system.
Sending the data to the things stack
Add a new case to the switch (data[1])
in the function prepareTxFrame()
, the case should be the address of the sensor.
//the first value in the array is the sensor adress, this switch checks which sensor values are present and formats the appdata correctly for sending
switch (data[1]) {
case 0x23: //light sensor
appDataSize = 6;
//
appData[0] = data[0]; //connector
appData[1] = data[1]; //sensor
//
appData[2] = (uint8_t)(data[2] >> 8); //lux value first byte
appData[3] = (uint8_t)(data[2]); //lux value second byte
break;
When creating the new case you need to define the appDataSize
which will be the amount of byte sized packages you want to send to the things stack.
the amount of packages will wary for each sensor case but the first two will always be
appData[0]: connector number
appData[1]: sensor address
appData[0] = data[0]; //connector
appData[1] = data[1]; //sensor
The next bytes will be sensor data. If you have sensor values that are only positive and under 65535 (uint16_t) you can add them in this way.
appData[2] = (uint8_t)(data[2] >> 8); //lux value first byte
appData[3] = (uint8_t)(data[2]); //lux value second byte
The cube cell can only send one byte at a time so we need to convert our 16bits into two 8bit chunks. Using (uint8_t)
and right shifting the bits 8 times we get the first 8 bits and send them, next we only send the last bits.
If you have negative values we need to do a bit more converting on the server side. So we need to send a signed 32bit int to the server which it will then turn into either a positive or negative value to be added to the database
This is done by right shifting the data 24, 16, 8 and 0 times
appData[2] = (uint8_t)(data[2] >> 24);
appData[3] = (uint8_t)(data[2]) >> 16; //We need to send 4 bytes of the value because this value can be negative,
appData[4] = (uint8_t)(data[2] >> 8); //it will be converted in the webserver to either negative or posititve
appData[5] = (uint8_t)(data[2]); //see the hexToPosOrNegNum function.
Lastly edit the appDataSize = x
to the last element number + 1, meaning if we look at the example above in the example with negative values, this number would be x = 6. This is required to create the correct array size.
Diagram of package setup from different sensor types.



Last updated