Questions about Electric IMP and the imp005

Hello,
I’m new in the Electric imp world (coming from Particle) and I would like to ask some questions:

What is the baud rate of the imp005 MCU device? I need it to have at least a 1mb baud rate. Is it something the imp005 can provide me? Or do you recommend something else?

I’m using the AWS cloud service. My plan is to get data from my sensor (it’s not a temp sensor, its much more complex sensor) to my imp005 MCU device than to my AWS cloud (then pull it to my backend…).
Do I need to push it first to the electric imp cloud BEFORE I can push it to AWS cloud? And, do the imp005 MCU device has any limit on the size of the data when pushing to and cloud service?

Thanks!

There are 3 uarts on imp005, and each has a different clocking setup (it’s… an interesting chip!).

uart.configure() returns the actual baudrate set (vs the requested one). Generally on a UART, up to ~5% baudrate error is just fine, because the drift only happens within a single byte - everything resyncs on the next start bit.

(the reason 5% is fine is because sampling is in the middle of each bit, and there are ~10 bits, so if you’re 5% high or low, the sampling point will have moved to + or - 50% of a bit time by the time the stop bit arrives).

eg, when you request 921,600bps on an imp005:

on uart0 you get 924,855bps (+0.35%). This will work fine.
on uart1 you get 779,166bps (-15.5%). This will NOT work.
on uart2 you get 935,000bps (+1.5%). This will work fine.

All data goes via the imp cloud, but there’s no limit aside from memory for sending to the cloud; generally you’ll want to send messages less than the TCP buffer size (as larger than that will block whilst the system waits for the server to ACK packets), but the TCP buffer size can go to 64kB.

You can easily sustain hundreds of kB/second upstream on an imp005. I just ran this example:

TRANSFER_SIZE <- (1024*1024)
BLOCK_SIZE    <- (16*1024)
NOOF_BLOCKS   <- (TRANSFER_SIZE / BLOCK_SIZE)

// Set max TCP transmit buffer size
imp.setsendbuffersize(65536);

blocks <- 0;
buffer <- blob(BLOCK_SIZE);

function loop() {
    if (blocks < NOOF_BLOCKS) {
        agent.send("data", buffer);
        blocks++;
        imp.wakeup(0, loop);
    } else {
        local end = hardware.millis();
        local duration = (end-start);
        local rate = (TRANSFER_SIZE/1024) / ((end-start)/1000.0);
        server.log(format("Transfer rate %.2fkB/s", rate));
        server.log(format("Duration %dms", duration));
    }
}

start <- hardware.millis();

loop();

…and I saw this (on a good internet connection obviously):

|2020-10-27T09:12:13.662 -07:00 |[Device] |Transfer rate 499.76kB/s
|2020-10-27T09:12:13.662 -07:00 |[Device] |Duration 2049ms

Hey hugo,

Thank you for your response!
We got out development kit imp005 and start using it and most of the things look fine.

As you said, we managed to use 921,600bps with uart0, but we have some problems.
This is our current device code:

local Frame = "";
local byte = 0;
local interval = 0;
// UART on imp005
local uart = hardware.uart0;

function SendDataToAgent() {
    // Send a 'Frame' to the Agent
    agent.send("Frame", Frame);
}

function Read() {
    local data = uart.read();
    if (data < 0) {
        // No data available
        server.log("Er");
    } else {
        byte = data & 255;
        interval = data >> 8;
        if (interval > 2578) {
            // 'byte' is the start of a Modbus frame
            // (4.5 character times at 19200 baud 8N2 is 2578 microseconds)
            SendDataToAgent();
            Frame = byte + " ";
        } else {
            // 'byte' belongs to the current frame
            Frame += byte + " ";
            }
    }
}
    
// Configure with timing
uart.configure(921600, 8, PARITY_NONE, 1, TIMING_ENABLED, Read);

Our problems:

  1. Each frame our agent gets from the device is about ~120 bytes on avg (while our sensor frame size is about ~500 bytes on avg). Do we have any limits when sending from the device to the agent? or there is something wrong in our device code? We saw the uart.setrxfifosize() function which we thought maybe limit us, but the default size is 80 and as I said, we are getting right now about ~120 on avg…

  2. In our code we are using a template from the Dev Center, where they are using there some kind of formula to calculate the interval size (2578 in our code). We don’t really understand how they calculate this number, and according to the comment we have there, they are using 19200 buad, while we are using 921600. How can we calculate the right interval for us?

A note on efficiency: generally you’d at least have a while loop in Read(), looping until there was no data left in the buffer as this reduces the overhead of the callback handler constantly being called. Personally I’d be concatenating binary onto Frame vs ascii, ie use Frame+=byte.tochar() each time as it’s much easier to parse at the other end too.

There are not limits sending in either way, aside from memory as I said before.

As you’re running at a fast rate, AND you are in timing mode (ie each entry in the FIFO is 4 bytes, not 1 byte) you should set the FIFO size larger (say 4kB). You need to set this before you call uart.configure.

Note that logging (server.log etc) is relatively slow - this is sending data over TLS - so don’t log on the device side if you’re in a high performance loop. Logging on the agent side doesn’t affect device performance.

On the interval:

time_us = (1000000.0/baudrate) * 4.5 * 11

4.5 = number of character times, 11 = bits in each character on the wire (8n2 = 1 start, 8 data, no parity, 2 stop = 11 bit times). Note that I have “1000000.0” vs just “1000000” to get a floating point division with the baudrate to preserve accuracy.

This returns 2578 for 19,200bps and 53 for 921,600bps.