For this project, we had to choose sensors that might be embedded on a Twizy. In this tutorial, we're going to read the sensors we choose and transmit data to the Sigfox Cloud. Thanks to Sigfox callbacks based on HTTP requests, we're be able to display data on Ubidots' dashboards.
Hardware UsedGrove Accelerometer 3 Axis (+/- 16g)
Grove Temperature and Humidity Sensor
- Accelerometer
This accelerometer is based on low power consumption ADXL345. It can be used for orientation and motion detection. It provides 3-axis acceleration info with a sensitivity of 3, 9 mg/LSB or 256 LSB/g. The sensor communicates with the MCU through an I2C bus. The component has a dedicated library which contains methods to do the initialization and read the raw data. First, you have to add the source and the header files in your work directory :
You create an instance of class ADXL345_I2C by indicating SDA and SCL pins you choose in arguments :
ADXL345_I2C accelerometer(PB_4, PA_7); // sda - scl
Then, you have to initialize the sensor by setting the power control, the resolution, the data rate and their format :
void Init_Accelerometer()
{
pc.printf("Starting ADXL345 test...\n");
wait(.001);
pc.printf("Device ID is: 0x%02x\n", accelerometer.getDeviceID());
wait(.001);
if (accelerometer.setPowerControl(0x00)){
pc.printf("didn't intitialize power control\n");
}
//Full resolution, +/-16g, 4mg/LSB.
wait(.001);
if(accelerometer.setDataFormatControl(0x0B)){
pc.printf("didn't set data format\n");
}
wait(.001);
//3.2kHz data rate.
if(accelerometer.setDataRate(ADXL345_3200HZ)){
pc.printf("didn't set data rate\n");
}
wait(.001);
//Measurement mode.
if(accelerometer.setPowerControl(MeasurementMode)) {
pc.printf("didn't set the power control to measurement\n");
}
}
We're now ready to read the 3-axis info :
accelerometer.getOutput(readings);
Xraw = (int16_t)readings[0];
Yraw = (int16_t)readings[1];
Zraw = (int16_t)readings[2];
The problem we face is that the accelerometer generates raw data, so you need to convert them into the unit of gravity, "g". The solution is to find the "zero G" and the scale (sensitivity) for each axis by placing the accelerometer along the axis on a flat surface.
/* For each axis, take the maximum value and the minimum value. */
zero_G = maxValue + minvalue;
scale = (maxValue - minValue) / 2;
After measurements, these are the values we found :
float zero_G_X = -7.0;
float zero_G_Y = 2.0;
float zero_G_Z = 2.0;
float scale_X = 247.0;
float scale_Y = 254.0;
float scale_Z = 252.0;
We now convert raw data in unit of g :
Xcalib = ((float)Xraw - zero_G_X) / scale_X;
Ycalib = ((float)Yraw - zero_G_Y) / scale_Y;
Zcalib = ((float)Zraw - zero_G_Z) / scale_Z;
- Current sensor
The component is based on a hall effect linear current sensor. It measures DC and AC current that reach 20A. We thought it might be helpful in a Twizy for a battery monitoring system. The current sensor provides directly a output voltage and has sensitivity of 100mV/A.
If we take a look at the datasheet, we found the Output Voltage versus the Input Current curve :
The zero Amper corresponds to the center of power supply range (+2, 5V). Consequently, to convert the Output Voltage in amperes, we need to consider the sensitivity and the VCC. We do not need any specific library to read the output voltage. However, we declare an instance of class AnalogIn provided by mbed to read an analog input. The read method provides a value between 0 and 1.
#define Sensitivity 0.1 // 100 mV/A
#define VCC 3.3 // We choose a 3V3 VCC
AnalogIn CurrentSensor(PA_4);
float currentIn = 0.0;
void readCurrent()
{
float outputVoltage = 0.0;
outputVoltage = CurrentSensor.read();
currentIn = ((outputVoltage * VCC) - 0.5 * VCC) / Sensitivity;
}
To smooth any fluctuations and unwanted variations, you had better implement an Averager function after the read method :
for (j = 0; j<1000; j++)
{
outputVoltage += CurrentSensor.read(); // 1000 samples
}
outputVoltage = outputVoltage / 1000;
- GPS Sensor
Concerning the GPS, we are going to use the GPS Grove unit. This is going to allow us to determine our position by reporting our longitude as well as our latitude through a GPGGA frame.
The acquisition and monitoring sensitivity of this unit can reach -1600 dBm. Here is an exemple of some other interesting data on this unit :
No need to import a library to program this unit. Actually, all we have to do is create an instance of the Serial class and read what the unit is reporting. At this moment, we will have to run a test on the first signs of each reported frame to make sure that it is, indeed, a GPGGA frame and then we will divide it in order to collect the longitude and latitude only. This data will have to be converted into degree to finish our program.
Here is where are situated : the longitude, latitude, sending hour of the frame, the number of satellites used and the altitude.
- 064036.289 = 06h 40m 36,289s
- 4836.5375 = Latitude in DMS
- 00740.9373 = Longitude in DMS
- 04 = Number of satellites used to calculate longitude and latitude
- 202.2 = altitude in meter
If there are incoming bytes (meaning that readable is true), we store all the bytes in the input buffer. Then, we test the first five bytes to retrieve and handle only GPGGA Frames :
As soon as we recognize a GPGGA frame, we divide and parse the frame so that we can extract the latitude and the longitude :
Finally, we convert the latitude and the longitude into degrees :
- Temperature and Humidity Sensor
This component is a high accuracy and ultra low power sensor ideal for IoT applications. It's based on a capacitive sensor element used for measuring relative humidity and a negative temperature coefficient (NTC) thermistor to measure temperature. The accuracy of the sensor can reach 0.3 degree in temperature and 2% in relative humidity.
To retrieve the temperature and the humidity informations, we use the DHT library available on mbed plateform.
First of all, we declare an instance of DHT class. The class DHT provides methods to get the temperature and the humidity. The constructor takes two arguments : an analog input of the MCU and the right type of sensor used (AM2302).
DHT capteur(PB_0, AM2302);
This done, if the method readData does not return an error, we are able to read the temperature and the humidity informations.
float temperature = 0.0f, humidity = 0.0f;
void getTempHumidity()
{
int error = 0;
wait(1.0);
error = capteur.readData();
if(error == 0)
{
temperature = capteur.ReadTemperature(CELCIUS);
humidity = capteur.ReadHumidity();
}
else
{
printf("Error: %d\n", error);
}
}
Sigfox Connectivity- What is Sigfox?
Sigfox is a lightweight IoT protocol that belongs to the LPWAN networks (Low Power Wide Area Network). In fact, Sigfoxe reduces energy consumption. Furthermore, it has a small payload.
- Serial communication
In order to communicate with the MCU, the Sigfox module uses a serial interface through the TX (transmit) and the RX (receive) pins.
To transmit data, you will have to declare an instance of class Serial provided by mbed. Specify the TX, RX pins of the Nucleo board. The method print() will send the bytes through the serial link. Be careful, you have to cast your integer and float data into bytes so that Sigfox will be able to treat the data. Because of small payload, you'll be limited to 12 bytes.
Serial sigfox(USBTX, USBRX); // pins PA2, PA3
void sendToCloudSigfox()
{
sigfox.printf("AT$SF=%02X%02X%02X%02X%02X%02X%02X%02X \r\n", temp, hum, x, y, z, current, latit, longit);
}
- Callbacks (request HTTP, POST method)
Sigfox Backend is able to send data received from the device associated to a device type over HTTP to a RESTful API.
To provide data (uplink), you have to specify the url of the server you want to exchange with and the token.
The Sigfox Backend will provide data from sensors into a JSON String.
Ubidots is a IoT plateform that enables to develop and deploy Internet-connected applications and solutions thanks to an easy-to-use Interface. Thanks to a REST API, the Cloud Plateform is able to receive and handle HTTP requests.
- Variables
The variables correspond to data that are encapsulated into the JSON String. The variables must bear the same name as the sensors' data so that the data will be well parsed. Consequently, we create as many variables as they are data from sensors.
- Dashboards
Ubidots enables to create widgets so that you can monitor the evolution of the temperature and the humidity over time, for instance.
To make sure our system easily fits in the Twizy, we designed a printed board on which each sensor is connected to the appropriate pins of the Nucleo Board through terminal blocks. It reduces the number of wires and enables to debug easily.
- Schematic
- Final prototype
Comments