Forum Replies Created
-
AuthorPosts
-
Below is the code I wrote several years ago that is still running on all our local tipping buckets. This was way before all the ModularSensors libraries and MMW portal, so things could be written differently now, but it can give you and idea on how the Mayfly handles the interrupt signal from the tipping bucket. There’s a 1-second delay after a tip is sensed to filter out any switch bouncing that sometimes occurs when a tip happens.
First you need to enable the pullup resistor on pin D10, which is already built in to the Mayfly board, you just have to close jumper SJ12 on the back of the Mayfly. Then this snippet of the code shows how to set up your sketch to look for a low trigger from the tipping bucket switch:
Arduino1234//enable the D10 pullup jumper on Mayfly solder jumper SJ12 in order for the next 2 lines to workpinMode(10, INPUT); //sets pin 10 as an inputattachInterrupt(2, pin10interrupt, LOW); //sets up an interrupt looking for a LOW trigger//connect one terminal of tipping bucket to Mayfly pin D10, connect other side of bucket switch to Mayfly groundI’ve sent the full sketch code to various people in the past few years who have requested it, and I thought it was already posted somewhere here on the forum, but if not, here’s the entire sketch. The biggest weak point is probably the delays that surround the Xbee radio wakeup and sleep, totaling 5 seconds. If a bucket tip were to happen during these delays, they don’t always get counted. A better option would be to use a milli timer to let the Mayfly go back to looking for tips and then execute the radio on and off functions independently, without using delays. But missing 5 seconds out of a 5 minute period isn’t too bad. (We’ve got Hobo event loggers on these rain gauges to record the actual data, these Mayfly boards are just there to transmit the live tips to our in-house data viz page for realtime viewing.) If the Mayfly has to do even more time-consuming things like cellular transmissions, then having the secondary device like the Trinket would ensure that no tips are missed. There are certainly more efficient ways to build a simple counter, but cost-wise, it’s hard to beat a $7 Trinket. If someone simply wants to count tips of a rain gauge (or any switch close/open event), then this code minus the telemetry stuff works great as an event counter/logger.
Arduino123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371#include <Wire.h>#include <avr/sleep.h>#include <avr/wdt.h>#include <SPI.h>#include <SD.h>//SODAQ libraries#include <RTCTimer.h>#include <Sodaq_DS3231.h>#include <Sodaq_PcInt_Mod.h>String targetURL;#define READ_DELAY 1//RTC TimerRTCTimer timer;String dataRec = ""; //a string to hold the data recordint currentminute, currenthour;long currentepochtime = 0;float boardtemp = 0.0;int daily_tips = 0; //the number of tipsvolatile int TipFlag = 0; //flag indicating that a tip has occurredvolatile int AlarmFlag = 0; //alarm flagint midnightflag = 0; //flag showing that it's midnightint batteryPin = A6;int batterysenseValue = 0;float batteryvoltage;#define XBEE_SleepPin 23 // sleep pin of the Xbee 900mhz radio module//RTC Interrupt pin#define RTC_PIN A7#define RTC_INT_PERIOD EveryMinute#define SD_SS_PIN 12//The data log file#define FILE_NAME "RainLog.txt"//Data header#define LOGGERNAME "Mayfly Rain Logger"#define DATA_HEADER "DateTime_UTC,TZ-Offset,Loggertime,BoardTemp,Battery_V,RainTips"void setup(){//Initialise the serial connectionSerial.begin(57600); //computer connectionSerial1.begin(9600); //xbee 900mhz radio module in bee headerrtc.begin();delay(200);pinMode(8, OUTPUT); //green LEDpinMode(9, OUTPUT); //red LEDgreenred4flash(); //blink the LEDs to show the board is onsetupLogFile();//Setup timer eventssetupTimer();//Setup sleep modesetupSleep();//Make first callSerial.println("Power On, running: mayfly_rain_1.ino");//enable the D10 pullup jumper on Mayfly solder jumper SJ12 in order for the next 2 lines to workpinMode(10, INPUT); //sets pin 10 as an inputattachInterrupt(2, pin10interrupt, LOW); //sets up an interrupt looking for a LOW trigger//connect one terminal of tipping bucket to Mayfly pin D10, connect other side of bucket switch to Mayfly ground}void loop(){//Update the timertimer.update();if (AlarmFlag == 1) {// Serial.println(" DS3231 Alarm ");AlarmFlag = 0;if (currenthour == 23 && currentminute == 59) {midnightflag = 1;digitalWrite(8, HIGH);dataRec = createDataRecord();logData(dataRec);assembleURL();delay(500);wakeXbee();delay(3000);sendviaXbee();delay(2500);sleepXbee();delay(500);String dataRec = "";digitalWrite(8, LOW);midnightflag = 0;daily_tips = 0; //start the daily total back to 0delay(200);}if (currentminute % 5 == 0) {digitalWrite(8, HIGH);dataRec = createDataRecord();logData(dataRec);assembleURL();delay(500);wakeXbee();delay(2000);sendviaXbee();delay(2500);sleepXbee();String dataRec = "";digitalWrite(8, LOW);delay(100);} //end if minute % 5 = 0rtc.clearINTStatus(); //This function call is a must to bring /INT pin HIGH after an interrupt.AlarmFlag = 0;} //end " if alarm_flag=1"if (TipFlag == 1) {// Serial.println(" TIP! ");daily_tips++;delay(1000);TipFlag = 0;}//Sleep//Serial.println("Going to sleep");systemSleep();// Serial.println("AWAKE!");}void showTime(uint32_t ts){//Retrieve and display the current date/timeString dateTime = getDateTime();//Serial.println(dateTime);}void setupTimer(){//Schedule the wakeup every minutetimer.every(READ_DELAY, showTime);//Instruct the RTCTimer how to get the current time readingtimer.setNowCallback(getNow);}void wakeISR(){AlarmFlag = 1;}void setupSleep(){pinMode(RTC_PIN, INPUT_PULLUP);PcInt::attachInterrupt(RTC_PIN, wakeISR);//Setup the RTC in interrupt modertc.enableInterrupts(RTC_INT_PERIOD);//Set the sleep modeset_sleep_mode(SLEEP_MODE_PWR_DOWN);}void systemSleep(){//Wait until the serial ports have finished transmittingSerial.flush();Serial1.flush();//The next timed interrupt will not be sent until this is clearedrtc.clearINTStatus();//Disable ADCADCSRA &= ~_BV(ADEN);//Sleep timenoInterrupts();sleep_enable();interrupts();sleep_cpu();sleep_disable();//Enbale ADCADCSRA |= _BV(ADEN);}String getDateTime(){String dateTimeStr;//Create a DateTime object from the current timeDateTime dt(rtc.makeDateTime(rtc.now().getEpoch()));currentepochtime = (dt.get()); //Unix time in secondscurrentminute = (dt.minute());currenthour = (dt.hour());//Convert it to a Stringdt.addToString(dateTimeStr);return dateTimeStr;}uint32_t getNow(){currentepochtime = rtc.now().getEpoch();return currentepochtime;}void greenred4flash() //fast blinks the LEDs 4 times{for (int i=1; i <= 4; i++){digitalWrite(8, HIGH);digitalWrite(9, LOW);delay(50);digitalWrite(8, LOW);digitalWrite(9, HIGH);delay(50);}digitalWrite(9, LOW);}void setupLogFile(){//Initialise the SD cardif (!SD.begin(SD_SS_PIN)){Serial.println("Error: SD card failed to initialise or is missing.");//Hang// while (true);}//Check if the file already existsbool oldFile = SD.exists(FILE_NAME);//Open the file in write modeFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Add header information if the file did not already existif (!oldFile){logFile.println(LOGGERNAME);logFile.println(DATA_HEADER);}//Close the file to save itlogFile.close();}void logData(String rec){//Re-open the fileFile logFile = SD.open(FILE_NAME, FILE_WRITE);//Write the CSV datalogFile.println(rec);//Close the file to save itlogFile.close();}String createDataRecord(){//Create a String type data record in csv formatString data = getDateTime();data += ",0,"; //adds UTC-timezone offset if your RTC is set to something other than UTCrtc.convertTemperature(); //convert current temperature into registersboardtemp = rtc.getTemperature(); //Read temperature sensor valuebatterysenseValue = analogRead(batteryPin);batteryvoltage = (3.3/1023.) * 4.7 * batterysenseValue;data += currentepochtime;data += ",";addFloatToString(data, boardtemp, 3, 1); //floatdata += ",";addFloatToString(data, batteryvoltage, 4, 2);data += ",";data += daily_tips;//Serial.print("Data Record: "); //if you want to print to the serial port//Serial.println(data);return data;}static void addFloatToString(String & str, float val, char width, unsigned char precision){char buffer[10];dtostrf(val, width, precision, buffer);str += buffer;}void assembleURL(){targetURL = "";targetURL = "http://somewebsite.com/capturescript.php?"; //put a php script on a server with mySQL database to capture the datatargetURL += "LoggerID=SL053&Loggertime=";targetURL += currentepochtime;targetURL += "&BoardTemp=";addFloatToString(targetURL, boardtemp, 3, 1); //floattargetURL += "&Battery=";addFloatToString(targetURL, batteryvoltage, 4, 2); //floattargetURL += "&RainTips=";targetURL += daily_tips;targetURL += "&Summary=";targetURL += midnightflag;}void sendviaXbee() {Serial1.println(targetURL);}void sleepXbee() {delay (1000);pinMode (XBEE_SleepPin,OUTPUT); // put XBee to sleepdigitalWrite(XBEE_SleepPin,HIGH);}void wakeXbee() {pinMode(XBEE_SleepPin,OUTPUT); // Set the "wake-up pin" to outputdigitalWrite(XBEE_SleepPin,LOW); // wake-up XBeedelay(500); //make sure that XBee is ready}void pin10interrupt(){TipFlag = 1; //a tip was detected, set the tip flag}Meter Group sensors like the Teros 12 come with either bare wires or 3.5mm stereo headphone jack plugs. Have you already purchased your sensors? If not, you can choose that option when you order. You can also request a custom cable length if you need longer cables than the default length, which I think is usually 3 meters on their soil sensors. Having them manufacture the sensors with extra cable length is highly preferred to splicing your own extensions on them. So depending on which cable termination you have on your sensor, you’ll need to figure how you want to connect them to your Arduino board. Are you using this setup indoors in a lab setting, or outside in the weather? How many sensors do you want to hook up to one Arduino board? How often are you going to take sensor readings? Are you going to be logging the data somehow? When you used the 10HS, did you use that with the Mega 2560, or something else?
The 10HS soil sensor has a simple analog voltage output that is easy to measure with an Arduino board by doing an analog voltage measurement. The Teros 12 has a digital output in either TTL or SDI-12 format. I’d recommend SDI-12, especially if you’re going to have more than one sensor connected to the same board, since then you can assign a different address to each one. The simplest library to do all of this is our SDI-12 library.
Is there a benefit to using a Trinket for counting the tips instead of using the Mayfly? I’ve built a bunch of tipping bucket recorders using only Mayfly boards by just connecting the bucket’s reed switch to the Mayfly pin D10 and using code to look for an interrupt to wake the Mayfly, increment the count, and go back to sleep. It records and transmits (via 900mhz Xbee) the count every 5 minutes, and resets the daily total at midnight. I’m guessing the Trinket is there so that you don’t miss counting a tip that comes in while the Mayfly is busy doing an uninterruptible time-consuming function, like transmitting the data via cell?
What kind of heater power are you using (AC or DC?), and what circuitry is controlling the heater on-off functionality? Are the ones recording the bad tips equipped with heaters or not? I’d remove the rain gauge reed switch wires from the Trinket so there’s no input at all to the Trinket, and then see if it continues recording phantom tips or not. If it is still recording bad tips, then your problem is with the Trinket. If the bad tips stop, then your problem is likely in the wires going to the gauge (a short somewhere, corrosion, or RFI or other signal interference) or with the reed switch failing (which I’ve seen before).
I just compiled and ran your code on my own Mayfly board (replacing the Loop function with the one I edited above), and commenting out anything relate to the Atlas sensors since I don’t have any here for testing, and the Mayfly board slept properly, woke up every minute and took a “sample”, wrote data to the card, and went back to sleep.
If you board isn’t waking up and you don’t even have the two header lines on your memory card, then that means your board isn’t even getting to the main loop. I would guess there’s problem with either your memory card, memory card socket, RTC chip or battery (you have the positive side of the coin cell facing up, right?), or something wrong in your sensor wiring that is either shorting something out or causing the sketch to lock up before it can run.
Is the board sleeping all the time and not waking? Or is it awake all the time and not sleeping? Is data being saved to the card or printed to the serial terminal?
It looks like this code was based on one of our old sleeping Mayfly logger example sketches, but there’s some stuff in the main Loop that is out of order. I’m assuming you’ve got the Atlas sensors connected to the I2C Grove port on the Mayfly. If you want to be able to switch their power on and off, then you need to move the small jumper on the headers pins next to those Grove ports to the 3.3v-SWITCHED position. Then you need to turn on the sensor power pin (D22) on and off in your code. Pin D8 is the green LED and your code sets it low once but never does anything else with it. I typically turn the green LED on when the board is awake and taking a reading, to let the use know that something is happening. You’ll also see the red LED by the Grove sockets turn on when the switched power is turned on, too. You’ve also got to run the sensor sampling function while the sensor power is on, and in your code you’ve got that happening after everything, including writing the data. I didn’t go through the entire sketch to look for all problems, but I think fixing a few things in the main Loop will get you most of the way to solving your issue. Here’s how I would write that section, but you might want to change it based on your goals.
123456789101112131415161718192021222324252627void loop() {//Update the timertimer.update();if(currentminute % sleepMinutes == 0) // change "2" to "5" to wake up logger every 5 minutes instead{ Serial.println("Multiple of 1! Initiating sensor reading and logging data to SDcard....");digitalWrite(8, HIGH); // turn the Green led pin ondigitalWrite(22, HIGH); // turn the switched power ondelay(5000); //wait 5 seconds for the sensors to stabilize?getdata(); //take readings from the Atlas sensorsdigitalWrite(22, LOW); //turn the switched power offdigitalWrite(8, LOW); //turn the green LED offString dataRec = createDataRecord(); //puts timestamp and sensor data into a stringlogData(dataRec); //Save the data record to the log fileSerial.println(dataRec); //Echo the data to the serial connection}delay(1000);systemSleep();}That’s correct, the main reason the ADS1115 is on the Mayfly is to give you much better resolution on analog measurements (16-bits versus the ATmega1284’s 10-bit ADC). It can also handle a much faster sampling rate and can take differential measurements. The standard ATmega analog inputs are still available for you to use, they’re just only accessible through the 2×10 header socket. The ADS1115 pins are available in two places: the 2×10 header socket and the 2 Grove sockets. Since they’re electrically the same pins, you can’t use more than one of those locations at a time. In your case, the Grove sockets are most convenient, but for anyone using a protoshield or building their own interface board for the Mayfly, then using the headers is more convenient.
Because the ADS1115 is a separate chip, you don’t have to declare the ADS1115 input pin numbers as A0, A1, etc. You just call them 0, 1, 2, or 3.
In your code, you can remove line 8 since you’re declaring an INT that you aren’t actually using anywhere. Or you could keep the line and just change ‘A3’ to ‘3’
Then in line 26, you can either change ‘A3’ to ‘TDSpin’ or simply ‘3’.
Assigning the pin number to the INT in line 8 is probably the best practice, and then use “TDSpin” everywhere else so that you can quickly change the number in line 8 to accommodate a sensor input on a different pin.
It’s fine if you have two different sensor inputs on adjacent Analog Aux pins on the Mayfly Grove port. Just make sure that both sensors are also each directly connected to the ground and Vcc pins.
Without having been to that station myself, it’s hard for me to guess why that station is having more battery trouble than your other ones. I’m guessing maybe it’s more shaded, or possibly the solar panel isn’t pointed in an optimal direction? You could also try putting a voltmeter on the panel on a sunny day and make sure it’s putting out around 6v (or even better, put an ammeter in line and read the charging current). We’ve had a couple of panels fail over time and don’t provide enough power to fully charge a battery. We’ve also seen issues where the charge controller circuitry on the Mayfly would partially fail and cause it to default to the trickle charge rate instead of full current charge. We’ve also had malfunctioning GPRSbee modules that tend to drain the battery power quicker even when asleep. I’ve also seen problems with microSD cards that start to go bad and draw excess current when the Mayfly is supposed to be sleeping.
So I’d say check your solar panel voltage, remove your GPRSbee, and replace the microSD card. If none of those fix the issue, put a new Mayfly in there. If the battery levels still fall, then replace the solar panel. If none of that solves the problem, then it’s likely just a shady location. If you’ve got deciduous trees around the station, sunlight should be improving in the coming weeks as the leaves fall, so that may also affect your results. We have a few stations that always struggle to stay charged during summer because of the full canopy above them, but they do great the rest of the year, even in the winter when the sun angle is lower.
-
AuthorPosts