Example showing the ublox Cellular GPS/GNSS module with the online PubNub service on an LPC4088 Experiment Base Board. This example uses an RTOS.

Dependencies:   C027_Support EALib LM75B PubNub mbed-rtos mbed picojson

Committer:
embeddedartists
Date:
Wed Oct 01 11:39:10 2014 +0000
Revision:
0:713518ea5028
First version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 0:713518ea5028 1 #include <cstring>
embeddedartists 0:713518ea5028 2
embeddedartists 0:713518ea5028 3 #include "mbed.h"
embeddedartists 0:713518ea5028 4 #include "rtos.h"
embeddedartists 0:713518ea5028 5 //#include "C12832.h"
embeddedartists 0:713518ea5028 6 //#include "MMA7660.h"
embeddedartists 0:713518ea5028 7 #include "MMA7455.h"
embeddedartists 0:713518ea5028 8 #include "LM75B.h"
embeddedartists 0:713518ea5028 9
embeddedartists 0:713518ea5028 10 #include "picojson.h"
embeddedartists 0:713518ea5028 11 #include "PubNub.h"
embeddedartists 0:713518ea5028 12
embeddedartists 0:713518ea5028 13 #include "sdram.h"
embeddedartists 0:713518ea5028 14
embeddedartists 0:713518ea5028 15 //------------------------------------------------------------------------------------
embeddedartists 0:713518ea5028 16 // You need to configure these cellular modem / SIM parameters.
embeddedartists 0:713518ea5028 17 // These parameters are ignored for LISA-C200 variants and can be left NULL.
embeddedartists 0:713518ea5028 18 //------------------------------------------------------------------------------------
embeddedartists 0:713518ea5028 19 #include "MDM.h"
embeddedartists 0:713518ea5028 20 //! Set your secret SIM pin here (e.g. "1234"). Check your SIM manual.
embeddedartists 0:713518ea5028 21 #define SIMPIN NULL
embeddedartists 0:713518ea5028 22 /*! The APN of your network operator SIM, sometimes it is "internet" check your
embeddedartists 0:713518ea5028 23 contract with the network operator. You can also try to look-up your settings in
embeddedartists 0:713518ea5028 24 google: https://www.google.de/search?q=APN+list */
embeddedartists 0:713518ea5028 25 #define APN "online.telia.se"
embeddedartists 0:713518ea5028 26 //! Set the user name for your APN, or NULL if not needed
embeddedartists 0:713518ea5028 27 #define USERNAME NULL
embeddedartists 0:713518ea5028 28 //! Set the password for your APN, or NULL if not needed
embeddedartists 0:713518ea5028 29 #define PASSWORD NULL
embeddedartists 0:713518ea5028 30 //------------------------------------------------------------------------------------
embeddedartists 0:713518ea5028 31
embeddedartists 0:713518ea5028 32 /* Demo of PubNub + the mbed application board. */
embeddedartists 0:713518ea5028 33
embeddedartists 0:713518ea5028 34 /* How to get things set up: */
embeddedartists 0:713518ea5028 35 /* 1. Tune in at the PubNub Developer Console, with the following
embeddedartists 0:713518ea5028 36 * keys (press Subscribe afterwards): */
embeddedartists 0:713518ea5028 37 const char pubkey[] = "demo";
embeddedartists 0:713518ea5028 38 const char subkey[] = "demo";
embeddedartists 0:713518ea5028 39 //const char channel[] = "mbed";
embeddedartists 0:713518ea5028 40 const char channel_pub[] = "mbed_data";
embeddedartists 0:713518ea5028 41 const char channel_sub[] = "mbed_cmd";
embeddedartists 0:713518ea5028 42 /* 2. Attach your mbed board to your computer. A folder should pop up like
embeddedartists 0:713518ea5028 43 * if you plug in a USB memory stick. */
embeddedartists 0:713518ea5028 44 /* 3. Open this example in the mbed web IDE and hit the Compile button. */
embeddedartists 0:713518ea5028 45 /* 4. A download popup with a .bin file will appear; save it in the USB
embeddedartists 0:713518ea5028 46 * mbed folder. */
embeddedartists 0:713518ea5028 47 /* 5. Press reset button on the mbed to start things up. */
embeddedartists 0:713518ea5028 48
embeddedartists 0:713518ea5028 49 /* You will see the board publish a "status" message that shows its
embeddedartists 0:713518ea5028 50 * current temperature and physical tilt. The board's LCD should
embeddedartists 0:713518ea5028 51 * print some progress messages regarding that. */
embeddedartists 0:713518ea5028 52 /* You can make the board do things too, by sending messages like:
embeddedartists 0:713518ea5028 53 * { "send_status": true }
embeddedartists 0:713518ea5028 54 * { "lcd": "Hi there!" }
embeddedartists 0:713518ea5028 55 * { "beep": true }
embeddedartists 0:713518ea5028 56 * { "led": {"r": 0.5, "g": 1, "b": 0} }
embeddedartists 0:713518ea5028 57 * Try it out! Paste these in the Message window and press the send icon.
embeddedartists 0:713518ea5028 58 */
embeddedartists 0:713518ea5028 59
embeddedartists 0:713518ea5028 60 Serial pc(USBTX, USBRX); // tx, rx
embeddedartists 0:713518ea5028 61 //MMA7660 MMA(P0_27, P0_28);
embeddedartists 0:713518ea5028 62 MMA7455 MMA(P0_27, P0_28);
embeddedartists 0:713518ea5028 63 LM75B tmp(P0_27, P0_28, LM75B::ADDRESS_1);
embeddedartists 0:713518ea5028 64 //C12832 lcd(D11, D13, D12, D7, D10);
embeddedartists 0:713518ea5028 65
embeddedartists 0:713518ea5028 66 PwmOut led_r(p25); // RGB LED with 3 PWM outputs for dimmer control
embeddedartists 0:713518ea5028 67 PwmOut led_g(p28);
embeddedartists 0:713518ea5028 68 PwmOut led_b(p26);
embeddedartists 0:713518ea5028 69 //PwmOut speaker(D6); // Speaker with PWM driver
embeddedartists 0:713518ea5028 70
embeddedartists 0:713518ea5028 71 DigitalOut led1(LED1);
embeddedartists 0:713518ea5028 72 DigitalOut led2(LED2);
embeddedartists 0:713518ea5028 73 DigitalOut led3(LED3);
embeddedartists 0:713518ea5028 74 DigitalOut led4(LED4);
embeddedartists 0:713518ea5028 75
embeddedartists 0:713518ea5028 76
embeddedartists 0:713518ea5028 77 bool forceStatusUpdate = true;
embeddedartists 0:713518ea5028 78
embeddedartists 0:713518ea5028 79 Mutex stdio_mutex;
embeddedartists 0:713518ea5028 80
embeddedartists 0:713518ea5028 81 #define safe_printf(...) do { \
embeddedartists 0:713518ea5028 82 stdio_mutex.lock(); \
embeddedartists 0:713518ea5028 83 pc.printf(__VA_ARGS__); \
embeddedartists 0:713518ea5028 84 stdio_mutex.unlock(); \
embeddedartists 0:713518ea5028 85 } while(0)
embeddedartists 0:713518ea5028 86
embeddedartists 0:713518ea5028 87 #define safe_print_pnub_err(__prefix) do { \
embeddedartists 0:713518ea5028 88 stdio_mutex.lock(); \
embeddedartists 0:713518ea5028 89 if (pnub_err) { \
embeddedartists 0:713518ea5028 90 pc.printf("%s: ERR, code = %d, line = %d\n", (__prefix), pnub_code, pnub_line); \
embeddedartists 0:713518ea5028 91 pnub_err = false; \
embeddedartists 0:713518ea5028 92 } \
embeddedartists 0:713518ea5028 93 stdio_mutex.unlock(); \
embeddedartists 0:713518ea5028 94 } while(0)
embeddedartists 0:713518ea5028 95
embeddedartists 0:713518ea5028 96 void pnub_err_handler(PubNubRes code, int line) {
embeddedartists 0:713518ea5028 97 stdio_mutex.lock();
embeddedartists 0:713518ea5028 98 if (code != PNR_OK) {
embeddedartists 0:713518ea5028 99 pc.printf("PbuNub:%d ERROR %d\n", line, code);
embeddedartists 0:713518ea5028 100 }
embeddedartists 0:713518ea5028 101 stdio_mutex.unlock();
embeddedartists 0:713518ea5028 102 }
embeddedartists 0:713518ea5028 103
embeddedartists 0:713518ea5028 104 void process_msg(PubNub &pn, const char *jsonmsg)
embeddedartists 0:713518ea5028 105 {
embeddedartists 0:713518ea5028 106 /* Use the picojson parser since we want to deal with complex messages.
embeddedartists 0:713518ea5028 107 * If you are short on memory, you can find an example for parsing simple
embeddedartists 0:713518ea5028 108 * JSON messages in the PubNub::subscribe() API docs. */
embeddedartists 0:713518ea5028 109 picojson::value msg;
embeddedartists 0:713518ea5028 110 std::string err = picojson::parse(msg, jsonmsg, jsonmsg + strlen(jsonmsg));
embeddedartists 0:713518ea5028 111 do {
embeddedartists 0:713518ea5028 112 if (!err.empty()) {
embeddedartists 0:713518ea5028 113 safe_printf("JSON parse: %s \n", err.c_str());
embeddedartists 0:713518ea5028 114 break;
embeddedartists 0:713518ea5028 115 }
embeddedartists 0:713518ea5028 116
embeddedartists 0:713518ea5028 117 if (msg.get("send_status").get<bool>()) {
embeddedartists 0:713518ea5028 118 //status_msg(pn);
embeddedartists 0:713518ea5028 119 forceStatusUpdate = true;
embeddedartists 0:713518ea5028 120 safe_printf("force_update\n");
embeddedartists 0:713518ea5028 121 break;
embeddedartists 0:713518ea5028 122 }
embeddedartists 0:713518ea5028 123 if (msg.get("lcd").is<std::string>()) {
embeddedartists 0:713518ea5028 124 safe_printf("in: %s \n", msg.get("lcd").get<std::string>().c_str());
embeddedartists 0:713518ea5028 125 break;
embeddedartists 0:713518ea5028 126 }
embeddedartists 0:713518ea5028 127 if (msg.get("beep").is<bool>()) {
embeddedartists 0:713518ea5028 128 //speaker = msg.get("beep").get<bool>() ? 0.5 : 0;
embeddedartists 0:713518ea5028 129 break;
embeddedartists 0:713518ea5028 130 }
embeddedartists 0:713518ea5028 131 if (msg.get("led").is<picojson::object>()) {
embeddedartists 0:713518ea5028 132 picojson::value led = msg.get("led");
embeddedartists 0:713518ea5028 133 safe_printf("Old RGB { %.3f, %.3f, %.3f }\n", led_r.read(), led_g.read(), led_b.read());
embeddedartists 0:713518ea5028 134 if (led.get("r").is<double>()) led_r = 1.0 - led.get("r").get<double>();
embeddedartists 0:713518ea5028 135 if (led.get("g").is<double>()) led_g = 1.0 - led.get("g").get<double>();
embeddedartists 0:713518ea5028 136 if (led.get("b").is<double>()) led_b = 1.0 - led.get("b").get<double>();
embeddedartists 0:713518ea5028 137 safe_printf("New RGB { %.3f, %.3f, %.3f }\n", led_r.read(), led_g.read(), led_b.read());
embeddedartists 0:713518ea5028 138 break;
embeddedartists 0:713518ea5028 139 }
embeddedartists 0:713518ea5028 140 } while(0);
embeddedartists 0:713518ea5028 141 }
embeddedartists 0:713518ea5028 142
embeddedartists 0:713518ea5028 143 void publish_thread(void const *args)
embeddedartists 0:713518ea5028 144 {
embeddedartists 0:713518ea5028 145 PubNub pn(pubkey, subkey);
embeddedartists 0:713518ea5028 146 Timer t;
embeddedartists 0:713518ea5028 147 t.start();
embeddedartists 0:713518ea5028 148 Timer tDbg;
embeddedartists 0:713518ea5028 149 int nDbg = 0;
embeddedartists 0:713518ea5028 150 float lastTemp = -3.75f;
embeddedartists 0:713518ea5028 151 while (true) {
embeddedartists 0:713518ea5028 152
embeddedartists 0:713518ea5028 153 /* Read sensors. */
embeddedartists 0:713518ea5028 154 int m[3];
embeddedartists 0:713518ea5028 155 MMA.read(m[0], m[1], m[2]);
embeddedartists 0:713518ea5028 156 float temp = (float)tmp;
embeddedartists 0:713518ea5028 157
embeddedartists 0:713518ea5028 158 /* Print on LCD. */
embeddedartists 0:713518ea5028 159 safe_printf("cur: mx=%3d, my=%3d, mz=%3d, t=%.2f \n", m[0], m[1], m[2], temp);
embeddedartists 0:713518ea5028 160
embeddedartists 0:713518ea5028 161 if (forceStatusUpdate || (temp != lastTemp)) {
embeddedartists 0:713518ea5028 162 lastTemp = temp;
embeddedartists 0:713518ea5028 163 forceStatusUpdate = false;
embeddedartists 0:713518ea5028 164
embeddedartists 0:713518ea5028 165 /* Prepare JSON message. */
embeddedartists 0:713518ea5028 166 char jsonmsg[128];
embeddedartists 0:713518ea5028 167 // snprintf(jsonmsg, sizeof(jsonmsg),
embeddedartists 0:713518ea5028 168 // "{\"status\":{\"mx\":%3d,\"my\":%3d,\"mz\":%3d,\"temp\":%.2f}}",
embeddedartists 0:713518ea5028 169 // m[0], m[1], m[2], temp);
embeddedartists 0:713518ea5028 170 snprintf(jsonmsg, sizeof(jsonmsg),
embeddedartists 0:713518ea5028 171 "%%7B%%22status%%22:%%7B%%22mx%%22:%3d,%%22my%%22:%3d,%%22mz%%22:%3d,%%22temp%%22:%.2f%%7D%%7D",
embeddedartists 0:713518ea5028 172 m[0], m[1], m[2], temp);
embeddedartists 0:713518ea5028 173
embeddedartists 0:713518ea5028 174 /* Publish on PubNub. */
embeddedartists 0:713518ea5028 175 safe_printf("before publishing\n");
embeddedartists 0:713518ea5028 176 led_r = 0;
embeddedartists 0:713518ea5028 177 tDbg.start();
embeddedartists 0:713518ea5028 178 // PubNubRes ret = pn.publish(channel_pub, jsonmsg);
embeddedartists 0:713518ea5028 179 PubNubRes ret = pn.publish_urlenc(channel_pub, jsonmsg);
embeddedartists 0:713518ea5028 180 tDbg.stop();
embeddedartists 0:713518ea5028 181 if (++nDbg == 10) {
embeddedartists 0:713518ea5028 182 safe_printf("10 requests took %d ms, i.e %d ms/req\n", tDbg.read_ms(), tDbg.read_ms()/10);
embeddedartists 0:713518ea5028 183 tDbg.reset();
embeddedartists 0:713518ea5028 184 nDbg = 0;
embeddedartists 0:713518ea5028 185 }
embeddedartists 0:713518ea5028 186
embeddedartists 0:713518ea5028 187 if (ret != PNR_OK) {
embeddedartists 0:713518ea5028 188 safe_printf("puberr: %d \n", ret);
embeddedartists 0:713518ea5028 189 //safe_print_pnub_err("pub");
embeddedartists 0:713518ea5028 190 forceStatusUpdate = true; // so that we can try again
embeddedartists 0:713518ea5028 191 }
embeddedartists 0:713518ea5028 192 led_r = 1;
embeddedartists 0:713518ea5028 193 safe_printf("after publishing\n");
embeddedartists 0:713518ea5028 194 }
embeddedartists 0:713518ea5028 195
embeddedartists 0:713518ea5028 196 wait_ms(100);
embeddedartists 0:713518ea5028 197 }
embeddedartists 0:713518ea5028 198 }
embeddedartists 0:713518ea5028 199
embeddedartists 0:713518ea5028 200 void subscribe_thread(void const *args)
embeddedartists 0:713518ea5028 201 {
embeddedartists 0:713518ea5028 202 PubNub pn(pubkey, subkey);
embeddedartists 0:713518ea5028 203 while(true) {
embeddedartists 0:713518ea5028 204 char *reply = NULL;
embeddedartists 0:713518ea5028 205 PubNubRes ret = pn.subscribe(channel_sub, &reply);
embeddedartists 0:713518ea5028 206 if (ret != PNR_OK) {
embeddedartists 0:713518ea5028 207 safe_printf("suberr: %d \n", ret);
embeddedartists 0:713518ea5028 208 //safe_print_pnub_err("sub");
embeddedartists 0:713518ea5028 209 wait(1.0);
embeddedartists 0:713518ea5028 210 continue;
embeddedartists 0:713518ea5028 211 }
embeddedartists 0:713518ea5028 212
embeddedartists 0:713518ea5028 213 if (reply) {
embeddedartists 0:713518ea5028 214 safe_printf("recv(%s)\n", reply);
embeddedartists 0:713518ea5028 215 process_msg(pn, reply);
embeddedartists 0:713518ea5028 216 }
embeddedartists 0:713518ea5028 217
embeddedartists 0:713518ea5028 218 wait(0.5); // avoid busy loop in bad situations
embeddedartists 0:713518ea5028 219 }
embeddedartists 0:713518ea5028 220 }
embeddedartists 0:713518ea5028 221
embeddedartists 0:713518ea5028 222 /** Cause the mbed to flash the BLOD (Blue LEDs Of Death) sequence
embeddedartists 0:713518ea5028 223 */
embeddedartists 0:713518ea5028 224 void mbed_die(void)
embeddedartists 0:713518ea5028 225 {
embeddedartists 0:713518ea5028 226 led1 = led2 = 1; led3 = led4 = 0; // lights out
embeddedartists 0:713518ea5028 227 while(1) {
embeddedartists 0:713518ea5028 228 led1 = 1;
embeddedartists 0:713518ea5028 229 led3 = 1;
embeddedartists 0:713518ea5028 230 wait_ms(100);
embeddedartists 0:713518ea5028 231 led2 = 1;
embeddedartists 0:713518ea5028 232 led1 = 0;
embeddedartists 0:713518ea5028 233 wait_ms(100);
embeddedartists 0:713518ea5028 234 led4 = 0;
embeddedartists 0:713518ea5028 235 led2 = 0;
embeddedartists 0:713518ea5028 236 wait_ms(100);
embeddedartists 0:713518ea5028 237 led3 = 0;
embeddedartists 0:713518ea5028 238 led4 = 1;
embeddedartists 0:713518ea5028 239 wait_ms(100);
embeddedartists 0:713518ea5028 240 }
embeddedartists 0:713518ea5028 241 }
embeddedartists 0:713518ea5028 242
embeddedartists 0:713518ea5028 243 int main()
embeddedartists 0:713518ea5028 244 {
embeddedartists 0:713518ea5028 245 if (sdram_init()) {
embeddedartists 0:713518ea5028 246 pc.printf("Failed to initialize SDRAM\n");
embeddedartists 0:713518ea5028 247 }
embeddedartists 0:713518ea5028 248
embeddedartists 0:713518ea5028 249 /* For debugging, you may find it useful to print memory usage
embeddedartists 0:713518ea5028 250 * stats. AvailableMemory may be flaky, but the following is nice.
embeddedartists 0:713518ea5028 251 * It will get printed to the USB serial port interface. */
embeddedartists 0:713518ea5028 252 //printf("%d: ", __LINE__); __heapstats((__heapprt)fprintf, stdout);
embeddedartists 0:713518ea5028 253
embeddedartists 0:713518ea5028 254 /* Generate a 800Hz tone using PWM hardware output */
embeddedartists 0:713518ea5028 255 //speaker.period(1.0/800.0); // 800hz period
embeddedartists 0:713518ea5028 256 led_r = led_g = led_b = 1.0; // lights out
embeddedartists 0:713518ea5028 257 led1 = led2 = 1; led3 = led4 = 0; // lights out
embeddedartists 0:713518ea5028 258
embeddedartists 0:713518ea5028 259 //lcd.cls();
embeddedartists 0:713518ea5028 260 //lcd.locate(0,0);
embeddedartists 0:713518ea5028 261
embeddedartists 0:713518ea5028 262 if (!tmp.open()) {
embeddedartists 0:713518ea5028 263 pc.printf("Failed to open LM75 temperature sensor\n");
embeddedartists 0:713518ea5028 264 }
embeddedartists 0:713518ea5028 265
embeddedartists 0:713518ea5028 266 // if (!MMA.testConnection())
embeddedartists 0:713518ea5028 267 // pc.printf("MMA error \n");
embeddedartists 0:713518ea5028 268
embeddedartists 0:713518ea5028 269 // Initialize the accelerometer
embeddedartists 0:713518ea5028 270 if (!MMA.setMode(MMA7455::ModeMeasurement)) {
embeddedartists 0:713518ea5028 271 printf("Unable to set mode for MMA7455!\n");
embeddedartists 0:713518ea5028 272 }
embeddedartists 0:713518ea5028 273
embeddedartists 0:713518ea5028 274 // Calibrate it. It does not matter if it is on a level surface
embeddedartists 0:713518ea5028 275 // as this test is only interested in relative values.
embeddedartists 0:713518ea5028 276 if (!MMA.calibrate()) {
embeddedartists 0:713518ea5028 277 printf("Failed to calibrate MMA7455!\n");
embeddedartists 0:713518ea5028 278 }
embeddedartists 0:713518ea5028 279
embeddedartists 0:713518ea5028 280 MDMRtos<MDMSerial> mdm;
embeddedartists 0:713518ea5028 281 //mdm.setDebug(4); // enable this for debugging issues
embeddedartists 0:713518ea5028 282 int i;
embeddedartists 0:713518ea5028 283 for (i = 1; i <= 10; i++) {
embeddedartists 0:713518ea5028 284 if (mdm.connect(SIMPIN, APN,USERNAME,PASSWORD)) {
embeddedartists 0:713518ea5028 285 printf("Connected\n");
embeddedartists 0:713518ea5028 286 mdm.setDebug(0); // disable debug again
embeddedartists 0:713518ea5028 287 break;
embeddedartists 0:713518ea5028 288 } else {
embeddedartists 0:713518ea5028 289 printf("Attempt %2d to connect to the modem FAILED.\n", i);
embeddedartists 0:713518ea5028 290 wait(1);
embeddedartists 0:713518ea5028 291 mdm.setDebug(min(i, 4)); // to add more and more debug output
embeddedartists 0:713518ea5028 292 }
embeddedartists 0:713518ea5028 293 }
embeddedartists 0:713518ea5028 294 if (i > 10) {
embeddedartists 0:713518ea5028 295 printf("Failed to connect to the modem\n");
embeddedartists 0:713518ea5028 296 mbed_die();
embeddedartists 0:713518ea5028 297 }
embeddedartists 0:713518ea5028 298
embeddedartists 0:713518ea5028 299 forceStatusUpdate = true;
embeddedartists 0:713518ea5028 300 //status_msg(pn);
embeddedartists 0:713518ea5028 301 // lcd.printf("pub... ");
embeddedartists 0:713518ea5028 302
embeddedartists 0:713518ea5028 303 Thread t_p(publish_thread);
embeddedartists 0:713518ea5028 304 Thread t_s(subscribe_thread);
embeddedartists 0:713518ea5028 305
embeddedartists 0:713518ea5028 306 while (1) {
embeddedartists 0:713518ea5028 307 Thread::wait(2000);
embeddedartists 0:713518ea5028 308 safe_printf(".\n");
embeddedartists 0:713518ea5028 309 }
embeddedartists 0:713518ea5028 310
embeddedartists 0:713518ea5028 311 mdm.disconnect();
embeddedartists 0:713518ea5028 312 mdm.powerOff();
embeddedartists 0:713518ea5028 313 }