I2C onReceive event (event based rather than using read)

I am porting a project from Particle Boron to imp006 and I am surprised and somewhat disappointed to see what appears to be the condition that the imp API does not have an event-based onReceive() way of data input data from an I2C device, whereas Particle does, and especially since Squirrel is said to be event-based.

I am sure this is something that can be worked through, but can someone guide me how to port the following C/Particle Boron/Arduino code to imp006?

const int BUF_LEN = 6152;
char BUFFER[BUF_LEN];
volatile int iReceived = 0;
void receiveEvent(int dCount) {
    if(iReceived < BUF_LEN) {
      while(Wire.available()>0) {
        BUFFER[iReceived % (BUF_LEN-1)] = Wire.read();
        iReceived = iReceived+1;
      }
    }
}

Wire.setSpeed(CLOCK_SPEED_400KHZ);
Wire.begin(0x59);
Wire.onReceive(receiveEvent);

After a thorough perscrutation of the relevant section of the IMP documentation (https://developer.electricimp.com/api/hardware/i2c), I have concluded that there is no way to do this without using an OS-blocking infinite loop.

How is it possible to intersperse i2c.read() calls with period waits for the OS to breath (by using imp.wakeup()), without missing data?

How large is the i2c receive buffer - and can it be adjusted?

Application: My mission-critical MCU sends (one-way) the imp006 6152 bytes of binary data periodically. There is no signaling or two-way communication. The rate at which the 6152 chunks arrive is variable. Typically the 6152 byte i2c write will happen every 20 - 40 seconds, however the imp must be able to handle up to 1Hz.

Any help is appreciated. This is a critical component of the system I have running with Particle devices that I hope to use imp006 (perhaps eventually exclusively) for.

Thanks!

The particle/arduino code style is essentially incorrect; an I2C slave cannot asynchronously send data to a master - it’s not like you can wait for more data to be received - as an I2C master, you have to clock the bus to receive data. I have a strong suspicion that “Wire.available()” just clocks in one more byte.

On the wire, if you’re reading 6152 bytes then as a bus master you’ll need to send 9*6152 clocks to retrieve it (plus the addressing phase). At 400kHz this will take 0.09s to do so no problem with bus utilization.

Possibly your other device is an I2C master, and the particle is a slave? The imp does not support I2C slave mode, which may be the problem here. If that’s the case, I’d advise using a UART instead, as UARTs are designed for async operation.

@hugo, thank you for the response. Given that my Teensy 3.5 “I2C 6152-packet transmitter” code uses “Wire.beginTransmission(0x59)”, and given that the Arduino doc page for this function states “Begin a transmission to the I2C slave device with the given address”, it would appear that I am indeed using the Particle as an I2C Slave and trying to do the same with the imp006.

This is quite unfortunate. This is not a deal-breaker, because I like everything else so much about the imp (e.g. stable and cheaper cellular), but it is a significant disadvantage. I recently designed and ordered some circuit boards that were predicated upon interchangeable Particle/imp usage using the I2C line. Since the Boron has only one UART (ridiculous right), the I2C is necessary.

I was hoping I could have a hybrid, interchangeable Partcle/Imp system for the telemetry option as I would gradually switch over to imp. This is especially because I am having pretty good results with cellular stability on a particular older version of their firmware before they ruined it.

Just to clarify, are you saying there is no possible way in existence, unlike the Particle Boron, to make the imp006 receive data from a Teensy 3.5 MCU over I2C which is running the code,
Wire2.beginTransmission(0x59);
Wire2.write(&myBytes[currentByteIdx], 1);
Wire2.endTransmission();
?

Thanks again for all your help.

So, making the Teensy do UART output for the same data should be easy - you may well be able to use the same pins on the device/PCB by using a software serial library. Would mean different firmware there though. A future revision could maybe send the same data out on two pins, both UART and I2C? (or fall back to UART if it sees no ACK for the slave address on I2C maybe).

There is no I2C slave support in impOS. Nobody has had a hard requirement for this in the entire existence of the imp platform (that I can remember offhand anyway!), hence it remained on the to-do list. The hardware is capable but there’s no software support.

Just a thought, which may or may not be practical in this case, but a number of imp pins support state-change callbacks, so you could write some code to write the data to a Teensy GPIO and an imp pin state-change handler to check for something like a low to high change and then buffer the incoming values after a fix period of time. First two bytes are the data length, if the size is not fixed.

I’ve bit-banged data this way from the imp, but there’s no reason I can see why it wouldn’t work in reverse, if you have access to code running on the Teensy

Thanks both. Unfortunately Hugo the I2C output pins I’m using on the Teensy are not able to be changed in code to UART. And smittyone’s idea could work, but it doesn’t seem as good as using one of the many available UARTs.

So I have chosen to accommodate this limitation on the imp006 by making my Teensy output this stream configurably on either its Serial1 output or second I2C channel depending on whether I’m using Particle or imp for that particular deployment.

@hugo I have a relevant question, since I need to redesign things for this cause anyways: how would you recommend I go about getting a board outline and pin footprint file for the imp006 breakout board into EasyEDA so that I can make an interface board to it which I can solder onto the back to interface with my Teensy? I believe there are a lot of potential customers like me who have an intermediate level of expertise sufficient to make their own PCB designs in EasyEDA or Kicad with manually soldered THT components but lacking the expertise to assemble their own imp006 custom design from scratch manually purchasing and soldering the Quectel modem, STM32, all the required circuitry which is already beautifully done on the Breakout Board, etc.

In other words, your imp006 Breakout Board can be incredibly useful to people in my category if there is an easy way to make a custom PCB of the same outline that can be mounted onto the back of the imp006 Breakout Board, making the desired connections with the exposed pins.

I only see Altium and Gerber files on your reference page. I have EasyEDA and have yet to graduate to a more professional tool. Do you know of anyone who has an ability or a general process to get the outline and pin layout into my PCB design tool of choice? In the meantime, I will see if there’s a way I can convert the Altium into EasyEDA.

My goal is to make an interface board for the imp006 Breakout Board that will let me truly interchange ElectricImp and Particle with my deployments until I can hopefully, gradually transition over to ElectricImp over time.

@hugo So, subsequent to my last post, I see EasyEDA has an Altium import feature, but the Altium source files need to be ASCII-encoded, whereas the ones provided on your website are UTF-8 encoded.

Hugo, could you post/send me the ASCIII-encoded Altium files for the imp006 Breakout Board, so that I can make an interface board to it without trying to manually recreate the outline and breakout pin layout, which would not be possible for me?

This would be tremendously helpful. Thank you!

Try this - I’ve no way to check it, but this is the PCB file exported in Altium ASCII - presuming you just wanted the PCB?

imp006-breakout-3.0-ascii.PcbDoc.zip (506.8 KB)

@hugo That works! Yes, just so that I can physically replicate the outline and make the pin connections with standard 2.54mm headers. This is excellent. My project now is to make my own imp006 Breakout Board backside interface board. I also needed an SD card for the imp, and this is a much more cost-effective way than buying the outrageously overpriced mikroBus SD card module. Thanks!

@hugo, could I get the DXF file for the imp006 Breakout Board board outline as well? This is not in the ZIP file on the reference site download.

DXF of mech layers attached…imp006-breakout.DXF.zip (397.8 KB)

@hugo Thanks! It is nice to have the full resolution file (however that does not have a full outline), however since my post I was actually able to generate a DXF of the complete outline from your first files. This will be helpful to anyone using EasyEDA or similar tool:Imp006BoardOutlineDXF_2020-09-09_18-29-492.zip (27.3 KB)

This topic was automatically closed after 60 days. New replies are no longer allowed.