A while ago, I created RohmMultiSensor – Arduino library to easily control multiple sensors from the ROHM Sensor Evaluation Kit. Since the first article came out, there were a few changes in the library API, which make measurements even easier than before. Also, RohmMultiSensor now includes 3D printed cases for each sensor and the shield!
In this article, we’ll cover some new and improved features of the library. We’ll also take a look at the 3D printed casings for the sensors and the shield.
First, let me explain how – and perhaps more importantly why – I changed the way measurements are done. In the previous version of the library, you called a function, which returned a value as the following:
float* accelValue = acc.measure();
While this approach is very intuitive and works well for most sensors, it’s not all that great for sensors that, by their nature, return more than one value. Accelerometer, for example, returns three values: acceleration in X, Y and Z axis. The function then has to return an array of three values. In C/C++ terms, this means returning a pointer to an array, dynamically allocating a new array and after the array is not needed anymore, manually deallocating it to free the memory.
delete[] accelValue;
Dynamically allocating arrays and deallocating them later is not uncommon in C/C++, however, it’s not the most intuitive for people who just started programming and don’t yet fully understand memory management and things like pointers.
To make the library useful even for those who just started with Arduino, the measurement system was changed: every sensor still has the original .measure() function. However, this function takes no arguments and doesn’t return anything. The values measured by the sensor are instead stored in a measurement variable, which is a part of the sensor’s class.
sensorAcc.measure(); // now we have data in the measurement variables Serial.println(sensorAcc.accelX); Serial.println(sensorAcc.accelY); Serial.println(sensorAcc.accelZ);
This new system also means the library is better equipped to deal with asynchronous measurements and interrupts.
Another major feature of the updated library is improved support for interrupts. In the old version, the only sensor that supported – and in fact required – interrupts was the BM1422GMV magnetometer. However, almost all of the sensors that use I2C bus also have some form of interrupt. That’s why the library now has interrupt support for KX022 accelerometer, with more on the way!
The way interrupts are implemented now is very simple: each time Arduino receives an interrupt from the sensor, the measurement variables are updated. This value is then considered valid, until a new interrupt arrives. At this point, a new value is pulled from the sensor and saved.
The following code shows you how to use both BM1422GMV and KX022 with interrupts.
// define the sensors we will use #define INCLUDE_BM1422GMV #define INCLUDE_KX022_1020 // include the library #include <RohmMultiSensor.h> // instantiate the KX022-1020 class using interrupt 0 KX022_1020 sensorAcc(INT_0); // instantiate the BM1422GMV class using interrupt 1 BM1422GMV sensorMag(INT_1); // define the interrupt service routines void acc_isr(void) { sensorAcc.setFlagDrdy(); } void mag_isr(void) { sensorMag.setFlagDrdy(); } void setup() { // begin serial communication Serial.begin(9600); Serial.println(); // begin the TWI (I2C) interface. // this function has to be called before any calls to .init()!Wire.begin(); // initialize KX022-1020 and BM1422GMV with the default values // we have to provide the interrupt service routines to the .init() sensorAcc.init(acc_isr); sensorMag.init(mag_isr); Serial.println("X[g]\tY[g]\tZ[g]\tX[uT]\tY[uT]\tZ[uT]"); } void loop() { // measure the sensor values sensorAcc.measure(); sensorMag.measure(); // print the values Serial.print(sensorAcc.accelX); Serial.print('\t'); Serial.print(sensorAcc.accelY); Serial.print('\t'); Serial.print(sensorAcc.accelZ); Serial.print('\t'); Serial.print(sensorMag.magX); Serial.print('\t'); Serial.print(sensorMag.magY); Serial.print('\t'); Serial.println(sensorMag.magZ); // wait 100 ms before the next measurement delay(100); }
And since KX022 doesn’t require interrupts to work, they can be disabled!
// define the sensor we will use #define INCLUDE_KX022_1020 // include the library #include <RohmMultiSensor.h> // instantiate the sensor's class with default settings KX022_1020 sensorAcc; // the above is equivalent to // KX022_1020 acc(INT_NONE); void setup() { // begin serial communication Serial.begin(9600); Serial.println(); // begin the TWI (I2C) interface. // this function has to be called before any calls to .init()! Wire.begin(); // initialize KX022-1020 with the default values sensorAcc.init(); Serial.println("X[g]\tY[g]\tZ[g]"); } void loop() { // measure the sensor values sensorAcc.measure(); // print the values to the serial port Serial.print(sensorAcc.accelX); Serial.print('\t'); Serial.print(sensorAcc.accelY); Serial.print('\t'); Serial.println(sensorAcc.accelZ); // wait 100 ms before the next measurement delay(100); }
The other major addition to the RohmMultiSensor library is the sensor covers! They allow you to mount the sensors anywhere you like and then connect them to the shield using some wires. This is very useful when you need to make sure that sensors like accelerometer and magnetometer are mounted securely and they provide accurate measurements, or when you need to case the sensor shield in a separate enclosure.
Mounting sensors into the casings is really easy. All the casings are made up of two parts: the bottom and the top.
Figure 1. Generic casing for sensors like KX022-1020 or BM1422GMV. Bottom half is on the left, top half is on the right.
Simply insert the sensor into the bottom part of the casing, so that the pins protrude to the other side.
Figure 2. Sensors inserted into the bottom half of the casing, bottom view (left) and top view (right).
Then, use two M3 bolts to secure the sensor in place.
Figure 3. Sensors mounted with two M3 bolts, bottom view (left) and top view (right).
Now just bolt the top half of the casing onto the bottom half with some M3 bolts. Done! The casing is now ready to be mounted onto virtually anything.
Figure 4. Assembled sensor casing.
Some of the sensors, like UV sensor or color sensor require optical contact with the outside world. The casings for those sensors are designed to allow the contact, as shown in the following picture.
Figure 5. Assembled UV sensor casing.
Of course, the list of the casings wouldn’t be complete without one for the actual shield itself! It lets you enclose the Arduino and the ROHM sensor evaluation shield in a convenient box, while still allowing you to mount sensors on top of it!
Figure 6. Casing for the shield
Figure 7. Top cover for the sensor shield
Figure 8. Bottom cover for the sensor shield
Certainly, there is still a lot to improve. As I stated above, there are other sensors that can use interrupts, so it would be nice to implement those as well. Also, it might be useful to have a function that will be able to reconfigure the sensor settings while the sketch is running. Currently, this is only done when the sensor class is being constructed when Arduino starts.
If you want to take a look at a more detailed documentation of the library, please visit the RohmMultiSensor Wiki. The wiki will always stay up-to-date with the latest changes and updates in the library. As always, thank you for reading the article and if you have suggestions for improvements, please leave them on my GitHub or in the comments below this article!