In my previous post Bee Bealthy - Blog 10: I2C Communication between Nicla Vision and MKR WAN 1310, I determined that I needed to resort to a two module contingency plan because my inability to use the Nicla Vision as a peripheral meant that I could not share the I2C bus with the Nicla Sense. So, I'm proceeding down that path. I started by printing another module housing and converting my proximity sensor test case to use the Nicla Vision as the I2C controller and the MKR WAN 1310 as the peripheral.
MKR1310_Nicla_Vision_Master_Proximity_TTN.ino
#include <Wire.h> #include <MKRWAN.h> #include "arduino_secrets.h" // Please enter your sensitive data in the Secret tab or arduino_secrets.h String appEui = SECRET_APP_EUI; String appKey = SECRET_APP_KEY; LoRaModem modem; #define SLAVE_ADDR 0x1B int dist; void setup() { Serial.begin(115200); // while(!Serial); Wire.begin(SLAVE_ADDR); Wire.onReceive(receiveEvent); // register event // change this to your regional band (eg. US915, AS923, ...) if (!modem.begin(US915)) { Serial.println("Failed to start module"); while (1) {} }; Serial.print("Your module version is: "); Serial.println(modem.version()); Serial.print("Your device EUI is: "); Serial.println(modem.deviceEUI()); int connected = modem.joinOTAA(appEui, appKey); while(!connected){ Serial.println("Retry..."); if(!modem.joinOTAA(appEui, appKey)){ Serial.println("Fail"); } else{ break; } }; // Set poll interval to 60 secs. modem.minPollInterval(60); // NOTE: independent of this setting, the modem will // not allow sending more than one message every 2 minutes, // this is enforced by firmware and can not be changed. } void loop() { static auto printTime = millis(); int err; if (millis() - printTime >= 65000) { byte payload[2]; payload[0] = highByte(dist); payload[1] = lowByte(dist); modem.beginPacket(); modem.write(payload, 8); err = modem.endPacket(true); if (err > 0) { Serial.println("Message sent correctly!"); } else { Serial.println("Error sending message :("); Serial.println("(you may send a limited amount of messages per minute, depending on the signal strength"); Serial.println("it may vary from 1 message every couple of seconds to 1 message every minute)"); } printTime = millis(); // Serial.println(String("Acceleration values: ") + accel.toString()); // Serial.println(String("temperature: ") + String(temperature.value(),3)); // Serial.println(String("humidity: ") + String(humidity.value(),3)); // Serial.println(String("pressure: ") + String(pressure.value(),3)); // Serial.println(String("gas: ") + String(gas.value(),3)); Serial.println(String("distance: ") + String(dist)); Serial.println(""); } // delay(100); // wait for 100ms before starting the next I2C transaction } // function that executes whenever data is received from master // this function is registered as an event, see setup() void receiveEvent(int howMany) { while(2 < Wire.available()) // loop through all but the last 2 { char c = Wire.read(); // receive byte as a character // Serial.print(c); // print the character } byte highByte = Wire.read(); // read the most significant byte byte lowByte = Wire.read(); // read the least significant byte dist = (highByte << 8) | lowByte; // combine the two bytes to form the integer value // Serial.println(reading); // print the integer }
Nicla_Vision_as_Shield_Proximity.ino
#include <Wire.h> #include "VL53L1X.h" VL53L1X proximity; #define SLAVE_ADDR 0x1B void setup() { Serial.begin(115200); Wire.begin(); // join i2c bus (address optional for master) Wire1.begin(); Wire1.setClock(400000); // use 400 kHz I2C proximity.setBus(&Wire1); if (!proximity.init()) { Serial.println("Failed to detect and initialize sensor!"); while (1); } proximity.setDistanceMode(VL53L1X::Long); proximity.setMeasurementTimingBudget(10000); proximity.startContinuous(10); } int reading = 0; void loop() { reading = proximity.read(); Serial.println(reading); Wire.beginTransmission(SLAVE_ADDR); // transmit to device SLAVE_ADDR Wire.write("proximity is "); // sends five bytes Wire.write((byte)(reading >> 8)); // send the most significant byte first Wire.write((byte)(reading & 0xFF)); // send the least significant byte Wire.endTransmission(); // stop transmitting delay(500); }
Then I needed to register the new MKR WAN 1310 with my Things application.
Here is the data received from the two modules shown in the Things Console:
And being passed through to the Node-Red UI via MQTT:
The uplink topics are tagged with the device ID automatically, so they are easy to separate.
The spikes in the proximity measurements were caused by putting my hand in front of the sensor. LoRaWAN update rates aren't really suited to doing something like proximity tracking. I'm updating at once per minute which works great for environmental measurements like temperature, humidity, pressure, and gas - but not so well for data like proximity or IMU readings. That type of data (including inference data) probably needs to have some interpretation (processing) before uploading.
I did verify by looking at the uplink data that channel hopping is occurring, but I have noticed when the units are in close proximity to each other that I am getting interference My test setup is in a room adjacent to the gateway, so I've got good RSSI (-30 to -50 dBm). I'll need to verify performance when the units are deployed outside.
Next I need to integrate the inferencing library and get the hardware and software cleaned up.