Notecard not compatible with Arduino Pro Mini?

From what I’ve read, Notecard is compatible with just about all micro controllers, even 8-bit MCU’s. However, I am having a bad time getting Notecard to work with an Atmega328p MCU (aka Arduino Pro Mini). Sure, the NotecardBasics Example works fine as is, however, as soon as I add a sensor to the code (in my case a HX711 ADC), the code fails to run.

#include <Notecard.h>
#include <Wire.h>
#include <HX711.h> 

#define myProductID " xxx.xxxx.xxxxxx:xxx"
Notecard notecard;

//HX711
HX711 scale; 
#define offset 12345
#define slope 18365.3

#define serialDebugOut Serial

void setup()
{
#ifdef serialDebugOut
    delay(2500);
    serialDebugOut.begin(115200);
    notecard.setDebugOutputStream(serialDebugOut);
#endif

 // Initialize the physical I/O channel to the Notecard
    Wire.begin();
    notecard.begin();

   J *req = notecard.newRequest("hub.set");
   JAddStringToObject(req, "product", myProductID);
   JAddStringToObject(req, "mode", "periodic");
   JAddStringToObject(req, "file", "data.qo");
   notecard.sendRequest(req);

  scale.begin(6, 7);
  
}

void loop()
{
    // Count the simulated measurements that we send to the cloud, and stop the demo before long.
    static unsigned eventCounter = 0;
    if (eventCounter++ > 2) {
        return;
    }

   //temp from Notecard
   double air_temp = 0;
    J *rsp = notecard.requestAndResponse(notecard.newRequest("card.temp"));
    if (rsp != NULL) {
        air_temp = JGetNumber(rsp, "value");
        notecard.deleteResponse(rsp);
    }
    // Do the same to retrieve the voltage that is detected by the Notecard on its V+ pin.
    double voltage = 0;
    rsp = notecard.requestAndResponse(notecard.newRequest("card.voltage"));
    if (rsp != NULL) {
        voltage = JGetNumber(rsp, "value");
        notecard.deleteResponse(rsp);
    }

// Weight
    float Weight = 0; 
    long NetRawWt = 0;
    
    scale.power_up();
    delay(10);
    NetRawWt = scale.read();
    NetRawWt = NetRawWt-offset;
    delay (10);
    Weight  = NetRawWt/slope;
    delay (10);
    scale.power_down(); 

  // add note
    J *req = notecard.newRequest("note.add");
    if (req != NULL) {
        JAddBoolToObject(req, "sync", true);
        J *body = JCreateObject();
        if (body != NULL) {
            JAddItemToObject(req, "body", body);
            JAddNumberToObject(body, "temp", air_temp);  
            JAddNumberToObject(body, "bat", voltage);
            JAddNumberToObject(body, "weight", Weight);
            JAddNumberToObject(body, "netrawwt", NetRawWt);
        }
      notecard.sendRequest(req); 
      
    }

    // Delay between measurements
    delay(15*1000);     // 15 seconds

}

The serial output looks like this:

09:53:49.433 -> {"err":"bad"}
09:53:49.433 -> {"req":"card.temp"}
09:53:49.528 -> {"value":22.9375,"calibration":-1.0}
09:53:49.528 -> {"req":"card.voltage"}
09:53:49.667 -> {"minutes":82,"hours":24,"mode":"high","value":4.2951838381303705,"vmin":4.29,"vmax":4.91,"vavg":4.8479166666666664,"daily":-0.13}
09:53:49.713 -> {"err":"bad"}
09:54:04.755 -> {"req":"card.temp"}
09:54:04.802 -> {"value":22.9375,"calibration":-1.0}
09:54:04.802 -> {"req":"card.voltage"}
09:54:04.896 -> {"minutes":83,"hours":24,"mode":"high","value":4.3029618749149151,"vmin":4.29,"vmax":4.91,"vavg":4.8479166666666664,"daily":-0.13}
09:54:05.363 -> {"err":"bad"}
type or paste code here

I think it may be a memory issue? The upload window shows “72% of program storage space used. Maximum is 30720 bytes. Global variables use 1011 bytes (49%) leaving 1037 bytes for local variables.” As soon as I add debug statements the program fails to run at all. If I take out the notecard json lines, the code runs fine, but of course no cloud sync. If I swap the HX711 for a BME280 sensor, the code also fails to run. If I remove the card.voltage and card.temp requests but leave the BME280 sensor, the code still won’t run. However, if I put the HX711 back instead of the BME280 (withoutcard.voltage and card.temp requests), the code runs fine! 1071 bytes free on the last iteration.
My questions are: Am I interpreting this correctly as a memory issue? If so, is there something else I can do to reduce memory, short of rewriting the code in assembly (which is beyond me)? If the Atmega328p really isn’t up to scratch (bearing in mind I have 2 more sensors I’d like to add), which other MCU could I use that is battery friendly?

Hi @rberkelm, {“err”:”bad”} is an error message sent by the library when it runs out of memory converting JSON to a string in SRAM. According to Microchip, the 328P is not recommended for new designs, and since you’re looking to add two additional sensors, I would recommend another MCU. Since you mentioned being battery friendly, maybe check out the Swan, which uses the same low-power STM32L4 chip on the Notecard.

1 Like

Thanks for the confirmation and advice. I will definitely check out the Swan.
Meantime, it would be good if Blues Wireless could amend their documentation on compatible micro controllers because much of it is quite misleading. E.g. in the Notecard datasheet - “Will support any MCU or single-board computer as your app processor - even low-memory, 8-bit microcontrollers.” There are many other similar untrue statements to trip up newcomers! The fact of the matter is that the JSON protocol is very memory hungry and you need a beefy MCU to do anything vaguely useful. From my brief foray, minimum 4kb of SRAM. Can you please pass this on within Blues?

Ray,

It’s not strictly necessary to use the note-c libary. It’s possible to use printf to format the json requests and send them directly to the serial port. Good idea making this option more prominent in our documentation. Here’s an example.

    #define serialNotecard Serial1

    ...
    // Initialize the serial port being used by the Notecard, and send a newline to clear out any data
    // that the Arduino software may have pending so that we always start sending commands "cleanly".
    // We use the speed of 9600 because the Notecard's RX/TX pins are always configured for that speed.
    serialNotecard.begin(9600);
    serialNotecard.println("\n");

    // This command (required) causes the data to be delivered to the Project on notehub.io that has claimed
    // this Product ID.  (see above)
    serialNotecard.println("{\"req\":\"service.set\",\"product\":\"" myProductID "\"}");
    ...

The code required for setting up serial (baud rate) and writing to it might be different on your platform, but this example shows how it would be done on Arduino. The note-c library is merely a convenience library to make it easier to work with the JSON. Thus, if your hardware doesn’t have enough memory to use that library, you’re not completely up a creek without a paddle.

Hope this helps,

Carl

By the way, the printf library itself may not fit into memory. An alternative method (used by one of our partners) is to use a sequence of “strcpy”, “strcat”, and “itoa” calls to build the JSON string that you need.

Please do let us know if you have more questions or ideas,

Carl

Thanks Carl. That’s a worth a shot, especially since I have my boards already printed… I’ll give it a go and report back.