Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: GPSLibrary GSM mbed-modifed Storage_Library Temp_Library Wakeup pH_Sensor
main.cpp@12:973566676eba, 2015-11-30 (annotated)
- Committer:
- ptcrews
- Date:
- Mon Nov 30 21:07:03 2015 +0000
- Revision:
- 12:973566676eba
- Parent:
- 11:cc22917d6634
- Child:
- 13:52fba498c00d
Mostly works. Need to fix fona power up/down.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| ptcrews | 1:83d3982f32d5 | 1 | #include "Adafruit_FONA.h" |
| ptcrews | 2:8de680cf7a19 | 2 | #include "WakeUp.h" |
| ptcrews | 1:83d3982f32d5 | 3 | #include "mbed.h" |
| tomli | 5:e180c73f4f70 | 4 | #include "MBed_Adafruit_GPS.h" |
| tomli | 5:e180c73f4f70 | 5 | #include <string> |
| ptcrews | 1:83d3982f32d5 | 6 | |
| tomli | 8:b607768bfa0a | 7 | // Cellular communication constants |
| ptcrews | 1:83d3982f32d5 | 8 | #define FONA_TX D8 |
| ptcrews | 1:83d3982f32d5 | 9 | #define FONA_RX D2 |
| ptcrews | 1:83d3982f32d5 | 10 | #define FONA_RST D3 |
| ptcrews | 1:83d3982f32d5 | 11 | #define FONA_RI D4 |
| ptcrews | 1:83d3982f32d5 | 12 | #define FONA_KEY D5 |
| ptcrews | 1:83d3982f32d5 | 13 | |
| tomli | 8:b607768bfa0a | 14 | // Global Positioning System constants |
| tomli | 5:e180c73f4f70 | 15 | #define GPS_TX D6 |
| tomli | 5:e180c73f4f70 | 16 | #define GPS_RX PB_11 |
| ptcrews | 12:973566676eba | 17 | #define GPS_EN D7 |
| tomli | 5:e180c73f4f70 | 18 | |
| tomli | 8:b607768bfa0a | 19 | // pH sensor constants |
| tomli | 5:e180c73f4f70 | 20 | #define PH_TX PC_10 |
| tomli | 5:e180c73f4f70 | 21 | #define PH_RX PC_11 |
| tomli | 5:e180c73f4f70 | 22 | |
| tomli | 10:01bbf4f1c250 | 23 | #define TMP_ANALOG A0 |
| tomli | 10:01bbf4f1c250 | 24 | #define ADC_CONVERSION 3.3/5.0 |
| tomli | 10:01bbf4f1c250 | 25 | AnalogIn temperature(TMP_ANALOG); |
| tomli | 10:01bbf4f1c250 | 26 | |
| tomli | 10:01bbf4f1c250 | 27 | #define READINGSIZE sizeof(struct reading) |
| ptcrews | 12:973566676eba | 28 | #define URL "http://requestb.in/sd2o2gsd" |
| tomli | 10:01bbf4f1c250 | 29 | |
| tomli | 8:b607768bfa0a | 30 | // Cellular communication global variables |
| ptcrews | 1:83d3982f32d5 | 31 | Adafruit_FONA fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI); |
| ptcrews | 1:83d3982f32d5 | 32 | Serial pcSerial(USBTX, USBRX); |
| ptcrews | 1:83d3982f32d5 | 33 | DigitalOut key(FONA_KEY); |
| ptcrews | 1:83d3982f32d5 | 34 | |
| tomli | 10:01bbf4f1c250 | 35 | struct reading { |
| tomli | 10:01bbf4f1c250 | 36 | float temperature; |
| tomli | 10:01bbf4f1c250 | 37 | float pH; |
| tomli | 10:01bbf4f1c250 | 38 | float latitude; //Signed positive if N, negative if S |
| tomli | 10:01bbf4f1c250 | 39 | float longitude; //Signed positive if E, negative if W |
| tomli | 10:01bbf4f1c250 | 40 | uint8_t day; |
| tomli | 10:01bbf4f1c250 | 41 | uint8_t month; |
| tomli | 10:01bbf4f1c250 | 42 | uint8_t year; |
| tomli | 10:01bbf4f1c250 | 43 | uint8_t hour; |
| tomli | 10:01bbf4f1c250 | 44 | uint8_t minutes; |
| tomli | 10:01bbf4f1c250 | 45 | }; |
| tomli | 10:01bbf4f1c250 | 46 | |
| tomli | 8:b607768bfa0a | 47 | // GPS global variables |
| tomli | 5:e180c73f4f70 | 48 | char c; //when read via Adafruit_GPS::read(), the class returns single character stored here |
| tomli | 5:e180c73f4f70 | 49 | Timer refresh_Timer; //sets up a timer for use in loop; how often do we print GPS info? |
| tomli | 5:e180c73f4f70 | 50 | const int refresh_Time = 2000; //refresh time in ms |
| tomli | 5:e180c73f4f70 | 51 | Serial gps_Serial(GPS_TX, GPS_RX); // Serial object for GPS |
| tomli | 5:e180c73f4f70 | 52 | Adafruit_GPS myGPS(&gps_Serial); |
| ptcrews | 12:973566676eba | 53 | DigitalOut gpsEN(GPS_EN); |
| tomli | 5:e180c73f4f70 | 54 | |
| tomli | 8:b607768bfa0a | 55 | // pH sensor global variables |
| tomli | 5:e180c73f4f70 | 56 | Serial ph_Serial (PH_TX, PH_RX); |
| tomli | 5:e180c73f4f70 | 57 | string sensorstring = ""; |
| tomli | 5:e180c73f4f70 | 58 | bool input_stringcomplete = false; |
| tomli | 5:e180c73f4f70 | 59 | bool sensor_stringcomplete = false; |
| tomli | 5:e180c73f4f70 | 60 | float pH; |
| tomli | 5:e180c73f4f70 | 61 | |
| tomli | 10:01bbf4f1c250 | 62 | struct reading lastReadingBuffer; |
| tomli | 10:01bbf4f1c250 | 63 | |
| tomli | 5:e180c73f4f70 | 64 | void setupPCSerial() { |
| tomli | 5:e180c73f4f70 | 65 | pcSerial.baud(115200); |
| tomli | 8:b607768bfa0a | 66 | pcSerial.printf("\n\n PC Serial connection established at 115200 baud.\n"); |
| tomli | 5:e180c73f4f70 | 67 | } |
| tomli | 5:e180c73f4f70 | 68 | |
| tomli | 8:b607768bfa0a | 69 | void disableContinuousMode() { |
| tomli | 8:b607768bfa0a | 70 | printf("pH sensor will NOT run in continous mode.\n"); |
| tomli | 5:e180c73f4f70 | 71 | if(ph_Serial.writeable() <= 0) printf("Not writable\n"); |
| tomli | 5:e180c73f4f70 | 72 | // disable continuous mode |
| tomli | 5:e180c73f4f70 | 73 | ph_Serial.printf("C,0"); |
| tomli | 5:e180c73f4f70 | 74 | ph_Serial.printf("%c", '\r'); |
| tomli | 5:e180c73f4f70 | 75 | printf("Waiting five seconds... "); |
| tomli | 5:e180c73f4f70 | 76 | wait(5); |
| tomli | 8:b607768bfa0a | 77 | } |
| tomli | 8:b607768bfa0a | 78 | |
| tomli | 8:b607768bfa0a | 79 | void setupPH() { |
| tomli | 8:b607768bfa0a | 80 | ph_Serial.baud(9600); |
| tomli | 8:b607768bfa0a | 81 | disableContinuousMode(); |
| tomli | 5:e180c73f4f70 | 82 | } |
| tomli | 5:e180c73f4f70 | 83 | |
| tomli | 5:e180c73f4f70 | 84 | void setupGPS() { |
| ptcrews | 12:973566676eba | 85 | gpsEN.write(1); |
| tomli | 5:e180c73f4f70 | 86 | myGPS.begin(9600); |
| tomli | 5:e180c73f4f70 | 87 | myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); //these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation |
| tomli | 5:e180c73f4f70 | 88 | myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); |
| tomli | 5:e180c73f4f70 | 89 | myGPS.sendCommand(PGCMD_ANTENNA); |
| tomli | 5:e180c73f4f70 | 90 | wait(1); |
| tomli | 5:e180c73f4f70 | 91 | refresh_Timer.start(); //starts the clock on the timer |
| tomli | 5:e180c73f4f70 | 92 | printf("setupGPS seems to be fine\n"); |
| tomli | 5:e180c73f4f70 | 93 | } |
| tomli | 5:e180c73f4f70 | 94 | |
| tomli | 5:e180c73f4f70 | 95 | void setup() { |
| tomli | 5:e180c73f4f70 | 96 | printf("\n=====\nSetup in Full Project\n"); |
| tomli | 5:e180c73f4f70 | 97 | setupPCSerial(); |
| ptcrews | 12:973566676eba | 98 | setupGPS(); |
| tomli | 5:e180c73f4f70 | 99 | setupPH(); |
| tomli | 5:e180c73f4f70 | 100 | } |
| tomli | 5:e180c73f4f70 | 101 | |
| tomli | 5:e180c73f4f70 | 102 | // Send default message to pH sensor, asking for data. |
| tomli | 5:e180c73f4f70 | 103 | void pHRequest() { |
| tomli | 5:e180c73f4f70 | 104 | printf("Sending pH request...\n"); |
| tomli | 5:e180c73f4f70 | 105 | if(ph_Serial.writeable() <= 0) printf("Not writable\n"); |
| tomli | 5:e180c73f4f70 | 106 | // request one reading |
| tomli | 5:e180c73f4f70 | 107 | ph_Serial.printf("R"); |
| tomli | 5:e180c73f4f70 | 108 | ph_Serial.printf("%c", '\r'); |
| tomli | 5:e180c73f4f70 | 109 | } |
| tomli | 5:e180c73f4f70 | 110 | |
| tomli | 5:e180c73f4f70 | 111 | void pHRead() { |
| ptcrews | 12:973566676eba | 112 | pHRequest(); |
| tomli | 5:e180c73f4f70 | 113 | printf("Reading pH information.\n"); |
| tomli | 5:e180c73f4f70 | 114 | if (ph_Serial.readable() > 0) { //if we see that the Atlas Scientific product has sent a character. |
| tomli | 5:e180c73f4f70 | 115 | printf("Receiving sensor string... ["); |
| tomli | 5:e180c73f4f70 | 116 | char inchar; |
| tomli | 5:e180c73f4f70 | 117 | while((inchar = (char)ph_Serial.getc()) != '\r') { |
| tomli | 5:e180c73f4f70 | 118 | sensorstring += inchar; |
| tomli | 5:e180c73f4f70 | 119 | printf("%c", inchar); |
| tomli | 5:e180c73f4f70 | 120 | } |
| tomli | 5:e180c73f4f70 | 121 | printf("] ...sensor string received!\n"); |
| tomli | 5:e180c73f4f70 | 122 | sensor_stringcomplete = true; |
| tomli | 10:01bbf4f1c250 | 123 | printf(sensorstring.c_str()); |
| tomli | 10:01bbf4f1c250 | 124 | // +1 is to get rid of control character |
| tomli | 10:01bbf4f1c250 | 125 | pH = atof(sensorstring.c_str()+1); //convert the string to a floating point number so it can be evaluated by the Arduino |
| tomli | 5:e180c73f4f70 | 126 | |
| tomli | 5:e180c73f4f70 | 127 | if (pH >= 7.0) { //if the pH is greater than or equal to 7.0 |
| tomli | 5:e180c73f4f70 | 128 | printf("high\n"); //print "high" this is demonstrating that the Arduino is evaluating the pH as a number and not as a string |
| tomli | 5:e180c73f4f70 | 129 | } |
| tomli | 5:e180c73f4f70 | 130 | |
| tomli | 5:e180c73f4f70 | 131 | if (pH <= 6.999) { //if the pH is less than or equal to 6.999 |
| tomli | 5:e180c73f4f70 | 132 | printf("low\n"); //print "low" this is demonstrating that the Arduino is evaluating the pH as a number and not as a string |
| tomli | 5:e180c73f4f70 | 133 | } |
| tomli | 5:e180c73f4f70 | 134 | |
| tomli | 5:e180c73f4f70 | 135 | //ph_Serial.printf("SLEEP"); |
| tomli | 5:e180c73f4f70 | 136 | //ph_Serial.printf("%c", '\r'); |
| tomli | 5:e180c73f4f70 | 137 | |
| tomli | 5:e180c73f4f70 | 138 | sensorstring = ""; //clear the string: |
| tomli | 5:e180c73f4f70 | 139 | sensor_stringcomplete = false; //reset the flag used to tell if we have received a completed string from the Atlas Scientific product |
| tomli | 5:e180c73f4f70 | 140 | } else { |
| tomli | 5:e180c73f4f70 | 141 | printf("pH sensor is not readable\n"); |
| tomli | 5:e180c73f4f70 | 142 | } |
| tomli | 5:e180c73f4f70 | 143 | } |
| tomli | 5:e180c73f4f70 | 144 | |
| tomli | 5:e180c73f4f70 | 145 | // n_queries is the number of times we query the GPS. We need something like 23000 characters. |
| tomli | 5:e180c73f4f70 | 146 | void GPSRead(int n_queries) { |
| ptcrews | 12:973566676eba | 147 | for(int i = 0; i < 20; i++){ |
| ptcrews | 12:973566676eba | 148 | wait(1); |
| ptcrews | 12:973566676eba | 149 | if(myGPS.fix) break; |
| ptcrews | 12:973566676eba | 150 | } |
| tomli | 5:e180c73f4f70 | 151 | pcSerial.printf("\n"); |
| tomli | 5:e180c73f4f70 | 152 | for (int i = 0; i < n_queries; i++) { |
| tomli | 5:e180c73f4f70 | 153 | c = myGPS.read(); //queries the GPS |
| tomli | 5:e180c73f4f70 | 154 | |
| tomli | 5:e180c73f4f70 | 155 | if (c) { pcSerial.printf("%c", c); } //this line will echo the GPS data if not paused |
| tomli | 5:e180c73f4f70 | 156 | |
| tomli | 5:e180c73f4f70 | 157 | //check if we recieved a new message from GPS, if so, attempt to parse it, |
| tomli | 5:e180c73f4f70 | 158 | if ( myGPS.newNMEAreceived() ) { |
| tomli | 5:e180c73f4f70 | 159 | if ( !myGPS.parse(myGPS.lastNMEA()) ) { |
| tomli | 5:e180c73f4f70 | 160 | continue; |
| tomli | 5:e180c73f4f70 | 161 | } |
| tomli | 5:e180c73f4f70 | 162 | } |
| tomli | 5:e180c73f4f70 | 163 | |
| tomli | 5:e180c73f4f70 | 164 | //check if enough time has passed to warrant printing GPS info to screen |
| tomli | 5:e180c73f4f70 | 165 | //note if refresh_Time is too low or pcSerial.baud is too low, GPS data may be lost during printing |
| tomli | 5:e180c73f4f70 | 166 | if (refresh_Timer.read_ms() >= refresh_Time) { |
| tomli | 5:e180c73f4f70 | 167 | refresh_Timer.reset(); |
| tomli | 5:e180c73f4f70 | 168 | pcSerial.printf("Time: %d:%d:%d.%u\n", myGPS.hour, myGPS.minute, myGPS.seconds, myGPS.milliseconds); |
| tomli | 5:e180c73f4f70 | 169 | pcSerial.printf("Date: %d/%d/20%d\n", myGPS.day, myGPS.month, myGPS.year); |
| tomli | 5:e180c73f4f70 | 170 | pcSerial.printf("Fix: %d\n", (int) myGPS.fix); |
| tomli | 5:e180c73f4f70 | 171 | pcSerial.printf("Quality: %d\n", (int) myGPS.fixquality); |
| tomli | 10:01bbf4f1c250 | 172 | |
| tomli | 10:01bbf4f1c250 | 173 | lastReadingBuffer.hour = myGPS.hour; |
| tomli | 10:01bbf4f1c250 | 174 | lastReadingBuffer.minutes = myGPS.minute; |
| tomli | 10:01bbf4f1c250 | 175 | lastReadingBuffer.day = myGPS.day; |
| tomli | 10:01bbf4f1c250 | 176 | lastReadingBuffer.month = myGPS.month; |
| tomli | 10:01bbf4f1c250 | 177 | lastReadingBuffer.year = myGPS.year; |
| tomli | 10:01bbf4f1c250 | 178 | lastReadingBuffer.latitude = 0.0; |
| tomli | 10:01bbf4f1c250 | 179 | lastReadingBuffer.longitude = 0.0; |
| tomli | 5:e180c73f4f70 | 180 | if (myGPS.fix) { |
| tomli | 10:01bbf4f1c250 | 181 | float mylatitude = myGPS.latitude; |
| tomli | 10:01bbf4f1c250 | 182 | if(myGPS.lat == 'S') |
| tomli | 10:01bbf4f1c250 | 183 | mylatitude *= -1; |
| tomli | 10:01bbf4f1c250 | 184 | float mylongitude = myGPS.longitude; |
| tomli | 10:01bbf4f1c250 | 185 | if(myGPS.lon == 'W') |
| tomli | 10:01bbf4f1c250 | 186 | mylongitude *= -1; |
| tomli | 10:01bbf4f1c250 | 187 | lastReadingBuffer.latitude = mylatitude; |
| tomli | 10:01bbf4f1c250 | 188 | lastReadingBuffer.longitude = mylongitude; |
| tomli | 5:e180c73f4f70 | 189 | pcSerial.printf("Location: %5.2f%c, %5.2f%c\n", myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon); |
| tomli | 5:e180c73f4f70 | 190 | pcSerial.printf("Speed: %5.2f knots\n", myGPS.speed); |
| tomli | 5:e180c73f4f70 | 191 | pcSerial.printf("Angle: %5.2f\n", myGPS.angle); |
| tomli | 5:e180c73f4f70 | 192 | pcSerial.printf("Altitude: %5.2f\n", myGPS.altitude); |
| tomli | 5:e180c73f4f70 | 193 | pcSerial.printf("Satellites: %d\n", myGPS.satellites); |
| tomli | 5:e180c73f4f70 | 194 | } |
| tomli | 5:e180c73f4f70 | 195 | } |
| tomli | 5:e180c73f4f70 | 196 | } |
| tomli | 5:e180c73f4f70 | 197 | pcSerial.printf("\n"); |
| tomli | 5:e180c73f4f70 | 198 | } |
| tomli | 5:e180c73f4f70 | 199 | |
| ptcrews | 3:6afcf4f3b2aa | 200 | void setupGSM() |
| ptcrews | 3:6afcf4f3b2aa | 201 | { |
| ptcrews | 3:6afcf4f3b2aa | 202 | printf("Starting FONA\n"); |
| ptcrews | 3:6afcf4f3b2aa | 203 | while(!fona.begin(9600)) { |
| ptcrews | 3:6afcf4f3b2aa | 204 | printf("Cannot find FONA\n"); |
| ptcrews | 3:6afcf4f3b2aa | 205 | wait(1); |
| ptcrews | 3:6afcf4f3b2aa | 206 | } |
| ptcrews | 3:6afcf4f3b2aa | 207 | fona.begin(9600); |
| ptcrews | 11:cc22917d6634 | 208 | printf("After begin\n"); |
| ptcrews | 12:973566676eba | 209 | fona.setGPRSNetworkSettings("pwg", "", ""); |
| ptcrews | 11:cc22917d6634 | 210 | printf("After set setting\n"); |
| ptcrews | 3:6afcf4f3b2aa | 211 | bool enable = false; |
| ptcrews | 3:6afcf4f3b2aa | 212 | while(enable != true) { |
| ptcrews | 3:6afcf4f3b2aa | 213 | fona.enableGPRS(true); |
| ptcrews | 3:6afcf4f3b2aa | 214 | fona.enableGPRS(false); |
| ptcrews | 3:6afcf4f3b2aa | 215 | enable = fona.enableGPRS(true); |
| ptcrews | 3:6afcf4f3b2aa | 216 | } |
| ptcrews | 11:cc22917d6634 | 217 | printf("After enable\n"); |
| ptcrews | 12:973566676eba | 218 | key.write(1); |
| ptcrews | 3:6afcf4f3b2aa | 219 | } |
| ptcrews | 3:6afcf4f3b2aa | 220 | |
| ptcrews | 2:8de680cf7a19 | 221 | void changeGSMPowerState() |
| ptcrews | 1:83d3982f32d5 | 222 | { |
| ptcrews | 1:83d3982f32d5 | 223 | key.write(0); |
| ptcrews | 1:83d3982f32d5 | 224 | wait(2); |
| ptcrews | 1:83d3982f32d5 | 225 | key.write(1); |
| ptcrews | 1:83d3982f32d5 | 226 | } |
| ptcrews | 1:83d3982f32d5 | 227 | |
| tomli | 10:01bbf4f1c250 | 228 | //Found this online and it claims that it resets ADC to work after deepsleep \_O_/ |
| tomli | 10:01bbf4f1c250 | 229 | void resetADC() |
| tomli | 10:01bbf4f1c250 | 230 | { |
| tomli | 10:01bbf4f1c250 | 231 | // Enable the HSI (to clock the ADC) |
| tomli | 10:01bbf4f1c250 | 232 | RCC_OscInitTypeDef RCC_OscInitStruct; |
| tomli | 10:01bbf4f1c250 | 233 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; |
| tomli | 10:01bbf4f1c250 | 234 | RCC_OscInitStruct.HSIState = RCC_HSI_ON; |
| tomli | 10:01bbf4f1c250 | 235 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; |
| tomli | 10:01bbf4f1c250 | 236 | HAL_RCC_OscConfig(&RCC_OscInitStruct); |
| tomli | 10:01bbf4f1c250 | 237 | } |
| tomli | 10:01bbf4f1c250 | 238 | |
| ptcrews | 3:6afcf4f3b2aa | 239 | void enterSleep(int msec) |
| ptcrews | 3:6afcf4f3b2aa | 240 | { |
| ptcrews | 12:973566676eba | 241 | gpsEN.write(0); |
| ptcrews | 2:8de680cf7a19 | 242 | if(msec > 0) WakeUp::set_ms(msec); |
| ptcrews | 2:8de680cf7a19 | 243 | deepsleep(); |
| tomli | 10:01bbf4f1c250 | 244 | resetADC(); |
| ptcrews | 12:973566676eba | 245 | gpsEN.write(1); |
| ptcrews | 2:8de680cf7a19 | 246 | } |
| ptcrews | 3:6afcf4f3b2aa | 247 | |
| tomli | 10:01bbf4f1c250 | 248 | bool sendDataOverHTTP(char* url, uint8_t* data, int dlength) |
| ptcrews | 3:6afcf4f3b2aa | 249 | { |
| ptcrews | 3:6afcf4f3b2aa | 250 | uint16_t statuscode; |
| ptcrews | 3:6afcf4f3b2aa | 251 | int16_t length; |
| tomli | 10:01bbf4f1c250 | 252 | if (!fona.HTTP_POST_start(url, "text/plain", data, dlength, &statuscode, (uint16_t *)&length)) { |
| ptcrews | 3:6afcf4f3b2aa | 253 | pcSerial.printf("Failed!\r\n"); |
| ptcrews | 3:6afcf4f3b2aa | 254 | return false; |
| ptcrews | 3:6afcf4f3b2aa | 255 | } |
| ptcrews | 3:6afcf4f3b2aa | 256 | while (length > 0) { |
| ptcrews | 3:6afcf4f3b2aa | 257 | while (fona.readable()) { |
| ptcrews | 3:6afcf4f3b2aa | 258 | char c = fona.getc(); |
| ptcrews | 3:6afcf4f3b2aa | 259 | pcSerial.putc(c); |
| ptcrews | 3:6afcf4f3b2aa | 260 | length--; |
| ptcrews | 3:6afcf4f3b2aa | 261 | if (! length) break; |
| ptcrews | 3:6afcf4f3b2aa | 262 | } |
| ptcrews | 3:6afcf4f3b2aa | 263 | } |
| ptcrews | 3:6afcf4f3b2aa | 264 | pcSerial.printf("\r\n****\r\n"); |
| ptcrews | 3:6afcf4f3b2aa | 265 | fona.HTTP_POST_end(); |
| ptcrews | 3:6afcf4f3b2aa | 266 | return true; |
| ptcrews | 3:6afcf4f3b2aa | 267 | } |
| ptcrews | 2:8de680cf7a19 | 268 | |
| tomli | 10:01bbf4f1c250 | 269 | //define where the EEPROM begins |
| tomli | 10:01bbf4f1c250 | 270 | #define stadr 0x08080000 |
| tomli | 10:01bbf4f1c250 | 271 | |
| tomli | 10:01bbf4f1c250 | 272 | //Our current offset in the EEPROM |
| tomli | 10:01bbf4f1c250 | 273 | int offset = 0; |
| tomli | 10:01bbf4f1c250 | 274 | int roffset = 0; |
| tomli | 10:01bbf4f1c250 | 275 | |
| tomli | 10:01bbf4f1c250 | 276 | //This function writes a byte of data to the EEPROM at the appropriate location. |
| tomli | 10:01bbf4f1c250 | 277 | //This is called by my writeEEPROMbytes. |
| tomli | 10:01bbf4f1c250 | 278 | //Use this if you want to write a single byte. |
| tomli | 10:01bbf4f1c250 | 279 | HAL_StatusTypeDef writeEEPROMByte(uint8_t data) |
| tomli | 10:01bbf4f1c250 | 280 | { |
| tomli | 10:01bbf4f1c250 | 281 | HAL_StatusTypeDef status; |
| tomli | 10:01bbf4f1c250 | 282 | int address = offset + stadr; |
| tomli | 10:01bbf4f1c250 | 283 | offset++; |
| tomli | 10:01bbf4f1c250 | 284 | HAL_FLASHEx_DATAEEPROM_Unlock(); //Unprotect the EEPROM to allow writing |
| tomli | 10:01bbf4f1c250 | 285 | status = HAL_FLASHEx_DATAEEPROM_Program(TYPEPROGRAMDATA_BYTE, address, data); |
| tomli | 10:01bbf4f1c250 | 286 | HAL_FLASHEx_DATAEEPROM_Lock(); // Reprotect the EEPROM |
| tomli | 10:01bbf4f1c250 | 287 | return status; |
| tomli | 10:01bbf4f1c250 | 288 | } |
| tomli | 10:01bbf4f1c250 | 289 | |
| tomli | 10:01bbf4f1c250 | 290 | //This function takes an array of bytes and its size and writes them to the EEPROM |
| tomli | 10:01bbf4f1c250 | 291 | //Use this if you want to write a lot of bytes. |
| tomli | 10:01bbf4f1c250 | 292 | void writeEEPROMbytes(uint8_t* data, uint8_t size) |
| tomli | 10:01bbf4f1c250 | 293 | { |
| tomli | 10:01bbf4f1c250 | 294 | for(int i = 0; i < size; i++) |
| tomli | 10:01bbf4f1c250 | 295 | { |
| tomli | 10:01bbf4f1c250 | 296 | writeEEPROMByte(data[i]); |
| tomli | 10:01bbf4f1c250 | 297 | } |
| tomli | 10:01bbf4f1c250 | 298 | } |
| tomli | 10:01bbf4f1c250 | 299 | |
| tomli | 10:01bbf4f1c250 | 300 | //This function reads a byte of data from the EEPROM at the offset passed in. |
| tomli | 10:01bbf4f1c250 | 301 | //This is called by my getEEPROM function |
| tomli | 10:01bbf4f1c250 | 302 | uint8_t readEEPROMByte(uint32_t off) { |
| tomli | 10:01bbf4f1c250 | 303 | uint8_t tmp = 0; |
| tomli | 10:01bbf4f1c250 | 304 | off = off + stadr; |
| tomli | 10:01bbf4f1c250 | 305 | tmp = *(__IO uint32_t*)off; |
| tomli | 10:01bbf4f1c250 | 306 | |
| tomli | 10:01bbf4f1c250 | 307 | return tmp; |
| tomli | 10:01bbf4f1c250 | 308 | } |
| tomli | 10:01bbf4f1c250 | 309 | |
| tomli | 10:01bbf4f1c250 | 310 | //Call this function when you have sent all the data in the EEPROM through GSM |
| tomli | 10:01bbf4f1c250 | 311 | //It just resets the offset to 0 so we start writing from the start. |
| tomli | 10:01bbf4f1c250 | 312 | void resetEEPROM() |
| tomli | 10:01bbf4f1c250 | 313 | { |
| tomli | 10:01bbf4f1c250 | 314 | offset = 0; |
| tomli | 10:01bbf4f1c250 | 315 | } |
| tomli | 10:01bbf4f1c250 | 316 | |
| tomli | 10:01bbf4f1c250 | 317 | //This takes an array of bytes an fills it with our entire EEPROM |
| tomli | 10:01bbf4f1c250 | 318 | //Call this function when you want to send the data over GSM |
| tomli | 10:01bbf4f1c250 | 319 | void getEEPROM(uint8_t *ptr) |
| tomli | 10:01bbf4f1c250 | 320 | { |
| tomli | 10:01bbf4f1c250 | 321 | int nbytes = offset; |
| tomli | 10:01bbf4f1c250 | 322 | printf("The number of bytes in the EEPROM is %d\n", nbytes); |
| tomli | 10:01bbf4f1c250 | 323 | for(int i = 0; i < nbytes; i++) |
| tomli | 10:01bbf4f1c250 | 324 | { |
| tomli | 10:01bbf4f1c250 | 325 | ptr[i] = readEEPROMByte(i); |
| tomli | 10:01bbf4f1c250 | 326 | } |
| tomli | 10:01bbf4f1c250 | 327 | //printf("WARNING DEBUG CODE BREAKS THINGS"); |
| tomli | 10:01bbf4f1c250 | 328 | //roffset += nbytes; |
| tomli | 10:01bbf4f1c250 | 329 | return; |
| tomli | 10:01bbf4f1c250 | 330 | } |
| tomli | 10:01bbf4f1c250 | 331 | |
| tomli | 10:01bbf4f1c250 | 332 | //function to get both the |
| tomli | 10:01bbf4f1c250 | 333 | float AD22100K_AI_value_to_Celsius() { // Convert Analog-input value to temperature |
| tomli | 10:01bbf4f1c250 | 334 | //1023 is to scale it up to the arduino read values. |
| tomli | 10:01bbf4f1c250 | 335 | float voltage = (int)((temperature.read() * ADC_CONVERSION) * 1023); |
| tomli | 10:01bbf4f1c250 | 336 | |
| tomli | 10:01bbf4f1c250 | 337 | float temperatureValue = (voltage * 0.217226044) - 61.1111111; // conversion factor simplified. |
| tomli | 10:01bbf4f1c250 | 338 | pcSerial.printf("AI_Val: %f\n", temperatureValue); |
| tomli | 10:01bbf4f1c250 | 339 | lastReadingBuffer.temperature = temperatureValue; |
| tomli | 10:01bbf4f1c250 | 340 | return temperatureValue; // 22.5 mV / °C; Ratiometric measurement, conversion valid for 5 V! |
| tomli | 10:01bbf4f1c250 | 341 | } |
| tomli | 10:01bbf4f1c250 | 342 | |
| ptcrews | 11:cc22917d6634 | 343 | bool sendDataToURL(uint8_t* data, int size) |
| tomli | 10:01bbf4f1c250 | 344 | { |
| tomli | 10:01bbf4f1c250 | 345 | changeGSMPowerState(); |
| tomli | 10:01bbf4f1c250 | 346 | setupGSM(); |
| ptcrews | 11:cc22917d6634 | 347 | printf("Setup GSM\n"); |
| ptcrews | 11:cc22917d6634 | 348 | bool res = sendDataOverHTTP(URL, data, size); |
| ptcrews | 11:cc22917d6634 | 349 | printf("After sent data\n"); |
| tomli | 10:01bbf4f1c250 | 350 | changeGSMPowerState(); |
| tomli | 10:01bbf4f1c250 | 351 | return res; |
| tomli | 10:01bbf4f1c250 | 352 | } |
| tomli | 9:b6e9751fbcba | 353 | |
| tomli | 9:b6e9751fbcba | 354 | // In the final version of this code: |
| tomli | 9:b6e9751fbcba | 355 | // We wake up ten times an hour to record information from our sensors. |
| tomli | 9:b6e9751fbcba | 356 | // but we wait until we have accumulated 240 measurements before we |
| tomli | 9:b6e9751fbcba | 357 | // start attempting to send away all our data. Once we successfully send |
| tomli | 9:b6e9751fbcba | 358 | // our information, we clear our memory and begin from the start. |
| tomli | 9:b6e9751fbcba | 359 | |
| tomli | 9:b6e9751fbcba | 360 | // TODO: Sleep mode. How does the Nucleo enter / exit sleep mode? |
| tomli | 9:b6e9751fbcba | 361 | // How do we power on / power off the other devices: |
| tomli | 9:b6e9751fbcba | 362 | // - GPS? |
| tomli | 9:b6e9751fbcba | 363 | // use the EN pin on the GPS |
| tomli | 9:b6e9751fbcba | 364 | // - pH sensor? |
| tomli | 9:b6e9751fbcba | 365 | // There's a sleep command |
| tomli | 9:b6e9751fbcba | 366 | // - Temperature sensor? |
| tomli | 10:01bbf4f1c250 | 367 | // Should automatically switch on / off when the nucleo enters deep sleep mode. |
| tomli | 9:b6e9751fbcba | 368 | // - GSM? |
| tomli | 9:b6e9751fbcba | 369 | // The enable pin is modified by changeGSMPowerStat(); |
| tomli | 9:b6e9751fbcba | 370 | // TODO: Web communication |
| tomli | 9:b6e9751fbcba | 371 | // - write server |
| tomli | 9:b6e9751fbcba | 372 | |
| ptcrews | 1:83d3982f32d5 | 373 | int main() |
| ptcrews | 1:83d3982f32d5 | 374 | { |
| tomli | 5:e180c73f4f70 | 375 | setup(); |
| tomli | 10:01bbf4f1c250 | 376 | int nreadings = 0; |
| tomli | 10:01bbf4f1c250 | 377 | bool toSend = false; |
| tomli | 5:e180c73f4f70 | 378 | while (true) { |
| tomli | 5:e180c73f4f70 | 379 | printf("~~~~~[pH]~~~~~\n"); |
| tomli | 5:e180c73f4f70 | 380 | pHRead(); |
| tomli | 10:01bbf4f1c250 | 381 | lastReadingBuffer.pH = pH; |
| tomli | 5:e180c73f4f70 | 382 | wait(1); |
| tomli | 10:01bbf4f1c250 | 383 | printf("~~~~~[GPS]~~~~~\n"); |
| tomli | 5:e180c73f4f70 | 384 | GPSRead(300000); |
| tomli | 5:e180c73f4f70 | 385 | wait(1); |
| tomli | 10:01bbf4f1c250 | 386 | printf("~~~~~[Temperature]~~~~~\n"); |
| tomli | 10:01bbf4f1c250 | 387 | AD22100K_AI_value_to_Celsius(); |
| tomli | 10:01bbf4f1c250 | 388 | wait(1); |
| tomli | 10:01bbf4f1c250 | 389 | writeEEPROMbytes((uint8_t *) &lastReadingBuffer, READINGSIZE); |
| tomli | 10:01bbf4f1c250 | 390 | nreadings++; |
| ptcrews | 12:973566676eba | 391 | if(nreadings == 10) |
| tomli | 10:01bbf4f1c250 | 392 | toSend = true; |
| tomli | 10:01bbf4f1c250 | 393 | if(toSend) { |
| tomli | 10:01bbf4f1c250 | 394 | struct reading* data = new struct reading[nreadings]; |
| tomli | 10:01bbf4f1c250 | 395 | getEEPROM((uint8_t*) data); |
| ptcrews | 11:cc22917d6634 | 396 | char buffer[((8+8+10+10+5*sizeof(int)+8)*nreadings) + 1]; |
| tomli | 10:01bbf4f1c250 | 397 | for(int i = 0; i < nreadings; i++) |
| tomli | 10:01bbf4f1c250 | 398 | { |
| ptcrews | 11:cc22917d6634 | 399 | int n = sprintf(buffer, "%8f %8f %10f %10f %d %d %d %d %d", data[i].temperature, data[i].pH, data[i].latitude, data[i].longitude, data[i].day, |
| ptcrews | 11:cc22917d6634 | 400 | data[i].month, data[i].year, data[i].hour, data[i].minutes); |
| ptcrews | 11:cc22917d6634 | 401 | printf("%s\n", buffer); |
| ptcrews | 11:cc22917d6634 | 402 | printf("%d\n", n); |
| ptcrews | 11:cc22917d6634 | 403 | printf("%d\n", (sizeof(buffer))); |
| ptcrews | 11:cc22917d6634 | 404 | printf("%d\n", data[i].minutes); |
| tomli | 10:01bbf4f1c250 | 405 | } |
| tomli | 10:01bbf4f1c250 | 406 | printf("HERE\n"); |
| ptcrews | 11:cc22917d6634 | 407 | bool res = sendDataToURL((uint8_t*) buffer, sizeof(buffer)); |
| tomli | 10:01bbf4f1c250 | 408 | if(res) { |
| tomli | 10:01bbf4f1c250 | 409 | toSend = false; |
| tomli | 10:01bbf4f1c250 | 410 | nreadings = 0; |
| tomli | 10:01bbf4f1c250 | 411 | resetEEPROM(); |
| tomli | 10:01bbf4f1c250 | 412 | } |
| tomli | 10:01bbf4f1c250 | 413 | delete[] data; |
| tomli | 10:01bbf4f1c250 | 414 | } |
| ptcrews | 12:973566676eba | 415 | //else changeGSMPowerState(); |
| tomli | 10:01bbf4f1c250 | 416 | /* |
| tomli | 10:01bbf4f1c250 | 417 | printf("Reading Size is %d\n", READINGSIZE); |
| tomli | 10:01bbf4f1c250 | 418 | printf("ROM Latitude: %f\n", verifier.latitude); |
| tomli | 10:01bbf4f1c250 | 419 | printf("ROM Longitude: %f\n", verifier.longitude); |
| tomli | 10:01bbf4f1c250 | 420 | printf("ROM pH: %f\n", verifier.pH); |
| tomli | 10:01bbf4f1c250 | 421 | printf("ROM Temperature: %f\n", verifier.temperature); |
| tomli | 10:01bbf4f1c250 | 422 | printf("ROM Day: %d\n", verifier.day); |
| tomli | 10:01bbf4f1c250 | 423 | printf("ROM Month: %d\n", verifier.month); |
| tomli | 10:01bbf4f1c250 | 424 | printf("ROM Year: %d\n", verifier.year); |
| tomli | 10:01bbf4f1c250 | 425 | printf("ROM Hour: %d\n", verifier.hour); |
| tomli | 10:01bbf4f1c250 | 426 | printf("ROM Minutes: %d\n", verifier.minutes); |
| tomli | 10:01bbf4f1c250 | 427 | */ |
| ptcrews | 12:973566676eba | 428 | wait(1); |
| ptcrews | 12:973566676eba | 429 | key.write(1); |
| ptcrews | 12:973566676eba | 430 | enterSleep(360000); |
| tomli | 5:e180c73f4f70 | 431 | } |
| ptcrews | 1:83d3982f32d5 | 432 | |
| ptcrews | 1:83d3982f32d5 | 433 | return 0; |
| ptcrews | 1:83d3982f32d5 | 434 | } |