Spark Core as I2C Slave

Is it yet possible to use the Spark Core as a slave I2C device?

Unfortunately I there is another device on the system that must be the master.

Thanks in advance,
Col

I believe that’s a yes!

I hope so. It’s probably my coding!

The Arduino (Master) code:

#include <Wire.h>

int xSpark = 0;

void setup()
{
  Wire.begin(); // join i2c bus 
}

void loop()
{
  if (xSpark > 7)
  {
    xSpark=0;
  }
  Wire.beginTransmission(4);
  Wire.write(xSpark);               // sends one byte
  Wire.endTransmission();
  xSpark++;
  delay(500);
}

The Spark Core (Slave) code:

int bedTemp;

void setup()
{
    Spark.variable("bedtemp", &bedTemp, INT);
    Wire.begin(4);                // join i2c bus with address #4
    Wire.onReceive(receiveEvent);    // register event
}

void loop()
{
}

void receiveEvent(int howMany)
{
    int bedTemp = Wire.read();        // receive byte as an integer
}

Any help would (again) be very much appreciated!!
Col

Spark Core as an I2C slave still isn’t working for me.

I have a Core linked to an Arduino Uno via I2C.

If I make the Core the Master then it works, if I swap the code (with relevant changes) it doesn’t work.

This is the working code:
Core (Master):

int x = 5;
int y = 8;

void setup()
{
    Wire.begin();
}

void loop()
{
    Wire.beginTransmission(4);
    Wire.write(x);
    Wire.write(y);
    Wire.endTransmission();
    x++;
    y++;
    delay(500);
}

Uno (Slave):

#include <Wire.h>

int LEDpin = 13;
int temp1 = 0;
int temp2 = 0;

void setup() {
    Wire.begin(4);
    Wire.onReceive(receiveEvent);

    pinMode(LEDpin, OUTPUT);
}

void loop() {
}

void receiveEvent(int howMany)
{
  if(Wire.available()) 
  {
    temp1 = Wire.read();
    temp2 = Wire.read();
    
    digitalWrite(LEDpin, HIGH);
    delay(50);
    digitalWrite(LEDpin, LOW);
    delay(50);
  }
}

The same code swapped round doesn’t work:
Uno (Master):

#include <Wire.h>
int x = 5;
int y = 8;
    
void setup()
{
  Wire.begin();
}
    
void loop()
{
  Wire.beginTransmission(4);
  Wire.write(x);
  Wire.write(y);
  Wire.endTransmission();
    
  x++;
  y++;
  delay(500);
}

Core (Slave):

int LEDpin = D7;
int temp1 = 0;
int temp2 = 0;

void setup() {
    Wire.begin(4);
    Wire.onReceive(receiveEvent);
    
    pinMode(LEDpin, OUTPUT);
}

void loop() {
}

void receiveEvent(int howMany)
{
  if(Wire.available()) 
  {
    temp1 = Wire.read();
    temp2 = Wire.read();
    
    digitalWrite(LEDpin, HIGH);
    delay(50);
    digitalWrite(LEDpin, LOW);
    delay(50);
  }
}

Any help would be GREATLY appreciated.
Col

Slave mode on the Core just doesn’t work right now. I’m hoping to have this fixed by the next big update.

1 Like

Ok, thank you :slight_smile:

I know you guys are working hard on lots of stuff!

2 Likes

new firmware but still no I2C slave :frowning:

Was just wondering if this issue is currently being worked on? Or potentially solved?

@kklumper, slave mode is available in the master repo if you compile with a local tool chain :smile:

@peekay123, thanks for the reply!

I’m getting strange behaviour… When the master sends a write command to the Core, the requestHandler is immediately triggered. Then, after the master sends the data and a stop bit the receiveHandler function is triggered which is normal. This code is working fine with an Arduino Mini.

It seems like the requestHandler is getting false triggered. I checked by sending a digital write to a separate pin and monitoring with a logic analyzer.

void receiveHandler(int numBytes)
{
    int i = 0;
    while (Wire.available()) {
        recvbuf[i++] = Wire.read();
        recvq = true;
    }
}

void requestHandler(void)
{
    Wire.write(sendbuf, (int) sendbuf[0] + 1);
}

@kklumper , can you post the rest of your code?

Here it is:

  #include "application.h"

SYSTEM_MODE(MANUAL);

#define BUFF_LENGTH 4
#define LE_CHR(a,b) ( ((a)<<8) | (b) ) // Macro for handling char bytes

byte sendbuf[BUFF_LENGTH], recvbuf[BUFF_LENGTH];

volatile boolean recvq      = false;

unsigned char MESSAGE[4]           = { 0, 0, 0, 0};
unsigned char COMMAND[4]           = { 3 , 'A', 'B', 'C'};
int cmd = 0;
int pushButton = D2;

void receiveHandler(int numBytes);
void requestHandler(void);

void checkBuf(void) 
{
  
  // Is there new data in the receive buffer?
  if (recvq){
    int cmd = (recvbuf[1] << 8) + recvbuf[2];
    
    if(cmd==LE_CHR('m','s'))
    {
        memcpy(sendbuf, COMMAND, sizeof COMMAND);
        digitalWrite(D5, LOW);
        delayMicroseconds(30);
        digitalWrite(D5, HIGH);
    }
   
    recvq = false;
  }
}

void setup()
{   
    Wire.begin(0x60);
    Wire.onReceive(receiveHandler);
    Wire.onRequest(requestHandler);
    
    pinMode(D5, OUTPUT);
    pinMode(D5, HIGH);
}

void loop()
{

   checkBuf();
}

void receiveHandler(int numBytes)
{
    int i = 0;
    while (Wire.available()) {
        recvbuf[i++] = Wire.read();
        recvq = true;
    }
}

void requestHandler(void)
{
    Wire.write(sendbuf, (int) sendbuf[0] + 1);
}

Each loop iteration checkBuf is called. If there is new data that matches ‘ms’, then it puts the values of COMMAND into the send buffer. Pulsing D5 low just tells the master that new data is ready to be read. The master will then send a read request. I don’t have the master code since it is in a black box, but this should be working since it was working on my Arduino.