Forum Replies Created
-
AuthorPosts
-
thomasvergoteParticipant
Thanks antapc and Phang Moh!
Just for info: my main problem was related to the use of LoraWAN, where logging stopped after a few days until resetting. When I went back to Lora with the radiohead library, I got good performance, with now a few months of logging. Any recurring issues now are related to external factors…
I do have loggers (different from the ones that triggered this discussion) which are continuously USB powered with no problems whatsoever.
thomasvergoteParticipantI am not sure if this is relevant, but as I am resetting, I have a number of Activation events on TTN. Sometimes I just get about two or three but this time it is quite particular: it took about 45 minutes before the last device was connected.After that it started working properly again, 5 min. interval for about an hour now.
thomasvergoteParticipantDear Phang Moh,
Thanks for your time, I really appreciate it, especially given your parenting duties!
My first prototype with the RadioHead library actually functioned for about two months. I know of another application (in caves), not using Lora but the same sensor library running for over a year. I have also tested my sensors in isolation and I don’t detect a problem. Even if I disconnect the sensors (leading to a simple zero reading), and put them outside, they run for a couple of hours upon reset and then stop (despite good battery values and a solar panel). As you make this comment, I am contemplating to revert one of the devices back to RadioHead to see if it keeps operating.
The frame count is increasing, sometimes missing two or three counts. Until it stops coming in altogether. I never saw a decrease or erratic behaviour.
The devices are employed in a land reclamation area that you could best describe as an artificial muddy lake. The area is pretty flat and the datalogger is floating in the water (about 60cm above the water line). The devices remain stationary. As gateway I have a RAK7249 which seems to be working nicely.
You do know that the Mini Ultra LoRaWAN’s RN2903 has yet to support AS923 band?
I even thought the same applied to the mini ultra pro v3, which is why my gateway is AS915. I expect this to work with the RN2903?
thomasvergoteParticipantAlso, from the TTN backend, does the frame counter went missing or jumps?
Yes, the frame counter jumps from time to time at TTN. As long as the logging starts again, I do not have much of a problem. Would this indicate an lmic issue? If so how can I resolve it? From your explanation and the link I am not sure how to resolve this properly.
It is also strange that the amount of frames before the datalogger disappears is very variable, for the same logger at the same location it sometimes works for 4 days and sometimes for 4 hours. The last few days I get nothing more than a few hours for all datalogger outside (at about 3 to 4km from my gateway). I am having a longer term reading from a datalogger inside, very close to the gateway. Once I reset, I get a proper connection within minutes however. Also, I am mostly operating at SF8BW125 for the further ones (sometimes at SF10). Soon resetting will not be an option anymore because of accessibility and it is highly critical to resolve this.
You need to call the SerialFlash write function to write data into it. You can do this but placing them at strategic places like when a EV_TXCOMPLETE takes place, or when you are reading the sensors. Then you could load a simple read from file firmware when you want to analyze them.
I am trying to do this but struggling with the library. When I try to make a file and write a char to it within the TTN code, it seems not to be registering anything. in any case, I am still at a loss on how to actually get intelligent error messages from this. I can probably just write an indicator after each part of the script to know where it stopped, but is that what you are suggesting? A simple example would be really nice.
Next to the 15 mini ultra pro v3’s, I now also ordered the Mini Ultra LoraWAN. I am going to set this up as well to see if it brings me any further.
These devices are used for a large port project for which no solution existed on the market yet. It is really important to get this working. If the Q&A on this forum does not resolve the issue, can we look into a bit of a closer discussion or consultancy to solve it?
thomasvergoteParticipantPhang Moh,
Thanks. First of all, I have set up 8 devices at the moment. They seem to stop at random (sometimes last for days, sometimes for hour). Sometimes I have devices that reappear after several hours or even a day but others just remain silent.
I am not sure how the duty cycle violation will affect the functionality: could it mean that the microcontroller stops sending altogether? I have followed your code which, I thought, handles duty cycle violation?
How should I ensure all error messages go to serialflash? Is it a matter of simply redefining Serial to SerialFlash? I guess I need to take care of the sleep cycle of the SerialFlash as well?
If this is caused by a hardware problem, say some moisture intrusion, would it have this kind of behavior (where it stops but then after reset works again for hours or days with 4 pressure sensors)? In that case, would I get anything from messages?
Thanks!
thomasvergoteParticipantHi Phang Moh,
I have since transitioned to LoraWAN via the Things Network. Still, from time to time I get the same issue: data stops coming in (sometimes after days of good operation) and after I reset I sometimes get another good period of readings (sometimes days, sometimes hours). I am working in a marine environment and I have not been able to trigger the issue while connected to a USB. I do not know what causes it, I only know that a reset gets it right again. What I would just need is a way to reset remotely or reset every so many hours regardless of what happens. Could I do anything of the kind programmatically or am I doomed to reset manually (which is quite difficult)?
btw. I have several sets and somehow, sooner or later, similar issues come up with all of them.
Thanks!
Code below.
/******************************************************************************* Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman Permission is hereby granted, free of charge, to anyone obtaining a copy of this document and accompanying files, to do whatever they want with them without any restriction, including, but not limited to, copying, modification and redistribution. NO WARRANTY OF ANY KIND IS PROVIDED. This example sends a valid LoRaWAN packet with payload "Hello, world!", using frequency and encryption settings matching those of the The Things Network. This uses OTAA (Over-the-air activation), where where a DevEUI and application key is configured, which are used in an over-the-air activation procedure where a DevAddr and session keys are assigned/generated for use with all further communication. Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in g1, 0.1% in g2), but not the TTN fair usage policy (which is probably violated by this sketch when left running for longer)! To use this sketch, first register your application and device with the things network, to set or generate an AppEUI, DevEUI and AppKey. Multiple devices can use the same AppEUI, but each device has its own DevEUI and AppKey. Do not forget to define the radio type correctly in config.h. *******************************************************************************/ #include <lmic.h> #include <hal/hal.h> #include <SPI.h> #include <Wire.h> #include <RTCZero.h> #include <SerialFlash.h> #define TCAADDR 0x70 #include <MS5803_14.h> MS_5803 sensor1 = MS_5803(4096); #define EUI64_CHIP_ADDRESS 0x50 #define EUI64_MAC_ADDRESS 0xF8 #define EUI64_MAC_LENGTH 0x08 #define MAX_DATA_SIZE 12 #define Serial SerialUSB RTCZero rtc; void tcaselect(uint8_t i) { if (i > 7) return; Wire.beginTransmission(TCAADDR); Wire.write(1 << i); Wire.endTransmission(); } // This EUI must be in little-endian format, so least-significant-byte // first. When copying an EUI from ttnctl output, this means to reverse // the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3, // 0x70. static const u1_t PROGMEM APPEUI[8] = ; void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8); } // This should also be in little endian format, see above. u1_t DEVEUI[EUI64_MAC_LENGTH]; void os_getDevEui (u1_t* buf) { memcpy(buf, DEVEUI, EUI64_MAC_LENGTH); } // This key should be in big endian format (or, since it is not really a // number but a block of memory, endianness does not really apply). In // practice, a key taken from ttnctl can be copied as-is. // The key shown here is the semtech default key. static const u1_t PROGMEM APPKEY[16] =; void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16); } static uint8_t data[MAX_DATA_SIZE]; static osjob_t sendjob; // Schedule TX every this many seconds (might become longer due to duty // cycle limitations). const unsigned TX_INTERVAL = 300; // Pin mapping const lmic_pinmap lmic_pins = { .nss = 5, .rxtx = LMIC_UNUSED_PIN, .rst = 3, .dio = {2, 6, LMIC_UNUSED_PIN}, }; void onEvent (ev_t ev) { Serial.print(os_getTime()); Serial.print(": "); switch (ev) { case EV_SCAN_TIMEOUT: Serial.println(F("EV_SCAN_TIMEOUT")); break; case EV_BEACON_FOUND: Serial.println(F("EV_BEACON_FOUND")); break; case EV_BEACON_MISSED: Serial.println(F("EV_BEACON_MISSED")); break; case EV_BEACON_TRACKED: Serial.println(F("EV_BEACON_TRACKED")); break; case EV_JOINING: Serial.println(F("EV_JOINING")); break; case EV_JOINED: Serial.println(F("EV_JOINED")); // Disable link check validation (automatically enabled // during join, but not supported by TTN at this time). LMIC_setLinkCheckMode(0); break; case EV_RFU1: Serial.println(F("EV_RFU1")); break; case EV_JOIN_FAILED: Serial.println(F("EV_JOIN_FAILED")); break; case EV_REJOIN_FAILED: Serial.println(F("EV_REJOIN_FAILED")); break; break; case EV_TXCOMPLETE: Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)")); if (LMIC.txrxFlags & TXRX_ACK) Serial.println(F("Received ack")); if (LMIC.dataLen) { Serial.println(F("Received ")); Serial.println(LMIC.dataLen); Serial.println(F(" bytes of payload")); } // Ensure all debugging messages are sent before sleep Serial.flush(); // Sleep for a period of TX_INTERVAL using single shot alarm rtc.setAlarmEpoch(rtc.getEpoch() + TX_INTERVAL); rtc.enableAlarm(rtc.MATCH_YYMMDDHHMMSS); rtc.attachInterrupt(alarmMatch); // USB port consumes extra current USBDevice.detach(); // Enter sleep mode rtc.standbyMode(); // Reinitialize USB for debugging USBDevice.init(); USBDevice.attach(); // Schedule next transmission to be immediately after this os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(1), do_send); break; case EV_LOST_TSYNC: Serial.println(F("EV_LOST_TSYNC")); break; case EV_RESET: Serial.println(F("EV_RESET")); break; case EV_RXCOMPLETE: // data received in ping slot Serial.println(F("EV_RXCOMPLETE")); break; case EV_LINK_DEAD: Serial.println(F("EV_LINK_DEAD")); break; case EV_LINK_ALIVE: Serial.println(F("EV_LINK_ALIVE")); break; default: Serial.println(F("Unknown event")); break; } } void do_send(osjob_t* j) { unsigned char counter; float batteryVoltage; int adcReading; int voltage; int pressure1; digitalWrite(LED_BUILTIN, HIGH); // Check if there is not a current TX/RX job running if (LMIC.opmode & OP_TXRXPEND) { Serial.println(F("OP_TXRXPEND, not sending")); } else { // ***** Battery monitor connection // // VBAT-----1M-----3M3-----GND // | // ---0.1uF---GND // | // A5 adcReading = analogRead(A5); // Discard inaccurate 1st reading adcReading = 0; // Perform averaging for (counter = 10; counter > 0; counter--) { adcReading += analogRead(A5); } adcReading = adcReading / 10; // Convert to volts batteryVoltage = adcReading * (4.3 / 1023.0); Serial.print(F("Battery: ")); Serial.print(batteryVoltage); Serial.println(F(" V")); // Pack float into int with 2 decimal point resolution voltage = batteryVoltage * 100; tcaselect(0); sensor1.initializeMS_5803(false); sensor1.readSensor(); pressure1 = sensor1.pressure(); data[0] = pressure1 >> 8;//voltage >> 8; data[1] = pressure1; tcaselect(1); sensor1.initializeMS_5803(false); sensor1.readSensor(); pressure1 = sensor1.pressure(); data[2] = pressure1 >> 8;//voltage >> 8; data[3] = pressure1; tcaselect(2); sensor1.initializeMS_5803(false); sensor1.readSensor(); pressure1 = sensor1.pressure(); data[4] = pressure1 >> 8;//voltage >> 8; data[5] = pressure1; tcaselect(3); sensor1.initializeMS_5803(false); sensor1.readSensor(); pressure1 = sensor1.pressure(); data[6] = pressure1 >> 8;//voltage >> 8; data[7] = pressure1; tcaselect(4); sensor1.initializeMS_5803(false); sensor1.readSensor(); pressure1 = sensor1.pressure(); data[8] = pressure1 >> 8;//voltage >> 8; data[9] = pressure1; data[10] = voltage >> 8; data[11] = voltage; // Prepare upstream data transmission at the next possible time. LMIC_setTxData2(1, data, sizeof(data), 0); Serial.println(F("Packet queued")); } // Next TX is scheduled after TX_COMPLETE event. digitalWrite(LED_BUILTIN, LOW); } void setDevEui(unsigned char* buf) { Wire.begin(); Wire.beginTransmission(EUI64_CHIP_ADDRESS); Wire.write(EUI64_MAC_ADDRESS); Wire.endTransmission(); Wire.requestFrom(EUI64_CHIP_ADDRESS, EUI64_MAC_LENGTH); // Format needs to be little endian (LSB...MSB) while (Wire.available()) { *buf-- = Wire.read(); } } void setup() { int count; unsigned char pinNumber; // ***** Put unused pins into known state ***** pinMode(0, INPUT_PULLUP); pinMode(1, INPUT_PULLUP); // D7-D13, A0(D14)-A5(D19), SDA(D20), SCL(D21), MISO(D22) for (pinNumber = 7; pinNumber <= 22; pinNumber++) { pinMode(pinNumber, INPUT_PULLUP); } // RX_LED (D25) & TX_LED (D26) (both LED not mounted on Mini Ultra Pro) pinMode(25, INPUT_PULLUP); pinMode(26, INPUT_PULLUP); // D30 (RX) & D31 (TX) of Serial pinMode(30, INPUT_PULLUP); pinMode(31, INPUT_PULLUP); // D34-D38 (EBDG Interface) for (pinNumber = 34; pinNumber <= 38; pinNumber++) { pinMode(pinNumber, INPUT_PULLUP); } // ***** End of unused pins state initialization ***** pinMode(LED_BUILTIN, OUTPUT); setDevEui(&DEVEUI[EUI64_MAC_LENGTH - 1]); while (!Serial && millis() < 10000); Serial.begin(115200); Serial.println(F("Starting")); Serial.print(F("DEVEUI: ")); for (count = EUI64_MAC_LENGTH; count > 0; count--) { Serial.print("0x"); if (DEVEUI[count - 1] <= 0x0F) Serial.print("0"); Serial.print(DEVEUI[count - 1], HEX); Serial.print(" "); } Serial.println(); // Initialize serial flash SerialFlash.begin(4); // Put serial flash in sleep SerialFlash.sleep(); // Initialize RTC rtc.begin(); // Use RTC as a second timer instead of calendar rtc.setEpoch(0); // LMIC init os_init(); // Reset the MAC state. Session and pending data transfers will be discarded. LMIC_reset(); LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100); // Start job (sending automatically starts OTAA too) do_send(&sendjob); } void loop() { Wire.begin(); tcaselect(0); sensor1.initializeMS_5803(false); os_runloop_once(); } void alarmMatch() { }
- This reply was modified 5 years, 8 months ago by thomasvergote.
thomasvergoteParticipantThe code can be found below. This did run nicely for 2 weeks, but seemed to get stuck at some point.
#include <SPI.h> #include <Wire.h> #include <RH_RF95.h> #include <MS5803_05.h> #include <SerialFlash.h> #include <RTCZero.h> #include <RH_RF95.h> #define TCAADDR 0x70 MS_5803 sensor1 = MS_5803(4096); RTCZero rtc; struct dataStruct{ float press_norm1 ; float temp1; float press_norm2 ; float temp2; unsigned long counter; }myData; byte tx_buf[sizeof(myData)] = {0}; RH_RF95 rf95(5, 2); /* Change these values to set the current initial date and time */ const uint8_t seconds = 0; const uint8_t minutes = 00; const uint8_t hours = 10; const uint8_t day = 20; const uint8_t month = 2; const uint8_t year = 17; const int radioDio0 = 2; const int flashChipSelect = 4; const int radioChipSelect = 5; unsigned char pinNumber; #define Serial SerialUSB void tcaselect(uint8_t i) { if (i > 7) return; Wire.beginTransmission(TCAADDR); Wire.write(1 << i); Wire.endTransmission(); } void setup() { // Switch unused pins as input and enabled built-in pullup for (pinNumber = 0; pinNumber < 23; pinNumber++) { pinMode(pinNumber, INPUT_PULLUP); } for (pinNumber = 32; pinNumber < 42; pinNumber++) { pinMode(pinNumber, INPUT_PULLUP); } pinMode(25, INPUT_PULLUP); pinMode(26, INPUT_PULLUP); if (!rf95.init()){} rf95.sleep(); SerialFlash.begin(flashChipSelect); SerialFlash.sleep(); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); // ***** IMPORTANT DELAY FOR CODE UPLOAD BEFORE USB PORT DETACH DURING SLEEP ***** delay(15000); pinMode(6, INPUT); pinMode(7, INPUT); digitalWrite(3, HIGH); pinMode(3, OUTPUT); digitalWrite(3, HIGH); // RTC initialization rtc.begin(); rtc.setTime(hours, minutes, seconds); rtc.setDate(day, month, year); // RTC alarm setting on every 15 s resulting in 1 minute sleep period rtc.setAlarmSeconds(1200); rtc.enableAlarm(rtc.MATCH_SS); rtc.attachInterrupt(alarmMatch); digitalWrite(LED_BUILTIN, LOW); USBDevice.detach(); rtc.standbyMode(); // Rocket Scream Mini Ultra Pro with the RFM95W only: // Ensure serial flash is not interfering with radio communication on SPI bus pinMode(4, OUTPUT); digitalWrite(4, HIGH); Serial.begin(9600); //while (!Serial) ; // Wait for serial port to be available if (!rf95.init()) Serial.println("init failed"); rf95.setModemConfig(RH_RF95::Bw31_25Cr48Sf512); rf95.setFrequency(915.0); rf95.setTxPower(20); Wire.begin(); tcaselect(0); sensor1.initializeMS_5803(false); } void loop() { unsigned char counter2; float batteryVoltage; int adcReading; int voltage; digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); adcReading = analogRead(A5); // Discard inaccurate 1st reading adcReading = 0; // Perform averaging for (counter2 = 10; counter2 > 0; counter2--) { adcReading += analogRead(A5); } adcReading = adcReading / 10; // Convert to volts batteryVoltage = adcReading * (4.3 / 1023.0); Serial.print(F("Battery: ")); Serial.print(batteryVoltage); Serial.println(F(" V")); // Pack float into int with 2 decimal point resolution voltage = batteryVoltage * 100; tcaselect(0); sensor1.readSensor(); myData.press_norm1=sensor1.pressure() / 10; myData.temp1=sensor1.temperature(); tcaselect(1); sensor1.readSensor(); myData.press_norm2=sensor1.pressure() / 10; myData.temp2=sensor1.temperature(); memcpy(tx_buf, &myData, sizeof(myData) ); byte zize=sizeof(myData); Serial.println("Sending to rf95_server"); Serial.println(myData.press_norm1); Serial.println(myData.press_norm2); rf95.send((uint8_t *)tx_buf, zize); rf95.waitPacketSent(); myData.counter=voltage; //myData.counter++; uint8_t buf[RH_RF95_MAX_MESSAGE_LEN]; uint8_t len = sizeof(buf); digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); rtc.standbyMode(); } void alarmMatch() { }
thomasvergoteParticipantI got it working!
The Wire.begin() is indeed necessary, but if I put it at the start of my setup(), it must be conflicting as nothing happens any more. If I put it at the end, it works. I am starting to finish up on full system now. Really like how it is working!
thomasvergoteParticipantI believe I have tried this already. I will try again once a field test is finished.
Do you have any alternative to use multiple I2Cs on the same address that is verified with the v3?
Also how is the backorder lead time on the v3 at this moment?
Thanks!
thomasvergoteParticipantHi Phang Moh,
Here is the simplest code working on a Pro Mini but not on the v3. It does work if I do not use the tcaselect. As you can see, it simply uses the wire library so I guess that is where the issue is, somehow.
#define TCAADDR 0x70 #include <Wire.h> #include <MS5803_14.h> #define Serial SerialUSB \\ for Ultra Pro v3 MS_5803 sensor1 = MS_5803(4096); MS_5803 sensor2 = MS_5803(512); void tcaselect(uint8_t i) { if (i > 7) return; Wire.beginTransmission(TCAADDR); Wire.write(1 << i); Wire.endTransmission(); } void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); Serial.println("Sensor 1:"); tcaselect(0); sensor1.initializeMS_5803(false); tcaselect(1); sensor2.initializeMS_5803(false); } void loop() { tcaselect(0); sensor1.readSensor(); Serial.println("Sensor 1: "+String(sensor1.pressure() / 10)+','+String(sensor1.temperature())); tcaselect(1); sensor2.readSensor(); Serial.println("Sensor 2: "+String(sensor2.pressure() / 10)+','+String(sensor2.temperature())); delay(1000); }
thomasvergoteParticipantOK! Then I better wait for the V3, RFM95W, 915MHz (then I am at least Singapore compliant :))
I would buy the antenna from you guys together, so I am flexible. My plan was to get your 915 MHz 5 dBi Dipole Antenna so that would be an SMA connector.
thomasvergoteParticipantGreat, thanks! This feels like a real good and compact solution.
So now I see that the mini pro ultra is out of stock in the RFM95W, 915MHz combination. Is it expect to come back in stock any time soon?
As I am looking at about 3km of max. reach (but pretty open, non-urban), the RFM69HCW is probably not feasible, but I see the V2, 915MHz is still in stock. So I can either go for that combination and limit my range, or for the v3, RFM95W, 868MHz. As I would do pure Lora at the moment, would it work (I read some conflicting stuff online)? I understand upgrading to LoRaWan will be out of the question then…
Thanks again!
-
AuthorPosts