Analog LED stay on connected to I2C slave for limited time while slave looks for new commands

Hello,

I have trouble understanding how to work with analog pins outside of the void loop().

I have a slave Arduino that receives commands as a byte. From my understanding, the slave Arduino keeps calling the receiveEvent() function and the requestEvent() function. It seems to ignore the void loop() function?

Now, the functions work in that they set my RGB LED for a split second as the function calls, however thereafter it goes off again. I would like it to stay on for a specific period (e.g. 3 seconds), while the slave keeps looping and looking for new commands.

I tried to set void receiveEvent(int howMany) as byte receiveEvent(int howMany) and then call the value to the void loop, but this threw an error as it expects void.

Could someone please advise? Relevant code below:

/*
  I2C Slave Demo
  i2c-slave-demo.ino
  Demonstrate use of I2C bus
  Slave receives character from Master and responds
  DroneBot Workshop 2019
  https://dronebotworkshop.com
*/

// Include Arduino Wire library for I2C
#include <Wire.h>
 
// Define Slave I2C Address
#define SLAVE_ADDR 9
 
// Define Slave answer size
#define ANSWERSIZE 5
 
// Define string with response to Master
String answer = "Hello";

 // define pins
const int redPin = 11;
const int greenPin = 10;
const int bluePin = 9;
//void setColourRgb(unsigned int red, unsigned int green, unsigned int blue);
//void pir_rgbTrigger(int pirValue); 
void setColourRgb(unsigned int red, unsigned int green, unsigned int blue);


void setup() {
  Wire.begin(SLAVE_ADDR);       // Initialize I2C communications as Slave
  Wire.onRequest(requestEvent); // Function to run when data requested from master
  Wire.onReceive(receiveEvent); // Function to run when data received from master
  
  // Setup Serial Monitor 
  Serial.begin(9600);
  Serial.println("I2C Slave Demonstration");
} 
 
void receiveEvent(int howMany) {
  // Read while data received
  while (0 < Wire.available()) {
    byte state = Wire.read();
    Serial.println(state);
    rgbState(state);
  }
  
  // Print to Serial Monitor
  //Serial.println("Receive event");
  
  //return x;
}
 
void requestEvent() {
 
  // Setup byte variable in the correct size
  byte response[ANSWERSIZE];
  
  // Format answer as array
  for (byte i=0;i<ANSWERSIZE;i++) {
    response[i] = (byte)answer.charAt(i);
  }
  
  // Send response back to Master
  Wire.write(response,sizeof(response));
  
  // Print to Serial Monitor
  //Serial.println("Request event");
}
 
void loop() {
  byte state;
  //state = receiveEvent();
  requestEvent();
  rgbState(state);
  // Time delay in loop
  delay(50);
}

void rgbState(byte state){
    unsigned int rgbColour[3];
    
    if (state == 0){
        rgbColour[0] = 0;
        rgbColour[1] = 0;
        rgbColour[2] = 0;
    }
    if (state >= 10 && state < 20){
        rgbColour[0] = 127;
        rgbColour[1] = 127;
        rgbColour[2] = 127;
    }
    else if (state >= 20 && state < 30)
    {
        rgbColour[0] = 127;
        rgbColour[1] = 0;
        rgbColour[2] = 0;
    }    

    setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
}

void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
}

looks like rgbState() is invoked for every character that is received and sets all the LEDs to 127 for values between 10-20. later characters causing the LED to be turned off

received event could turn on an LED, set a flag and capture a timestamp. loop() could conditionally check if the flag is set and check if a time has expired since the timestamp is set to turn off the LED

1 Like

Great, thank you.