I2C Message issue between Int and Byte message?

Good day,

I have an error with my code:

C:\Users\conno\OneDrive\Documents\Arduino\sketch_jul16a\sketch_jul16a.ino: In function 'void setup()':
C:\Users\conno\OneDrive\Documents\Arduino\sketch_jul16a\sketch_jul16a.ino:34:30: warning: invalid conversion from 'byte (*)() {aka unsigned char (*)()}' to 'void (*)(int)' [-fpermissive]
   Wire.onReceive(receiveEvent); // Function to run when data received from master
                              ^
In file included from C:\Users\conno\OneDrive\Documents\Arduino\sketch_jul16a\sketch_jul16a.ino:11:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\Wire\src/Wire.h:76:10: note:   initializing argument 1 of 'void TwoWire::onReceive(void (*)(int))'
     void onReceive( void (*)(int) );
          ^~~~~~~~~

The master code which sends a byte (relevant function is "masterToSlave":

// CLOCK
    /* CLOCK NOT WORKING PROPERLY. THEREFORE COMMENTED OUT. STATES SOMETHING ABOUT NOT ABLE TO CONVERT STRING TO 
    *      CHAR, THIS MAY HAVE TO DO WITH THE ISSUE
    * SEMI-FINAL_RTC Clock. WORKS WHEN SECONDARY ARDUINO SDA/SCL NOT CONNECTED, OR SDA/SCL CONNECTED WITH POWER.
     DOES NOT WORK WHEN SDA/SCL FROM SECONDARY ARDUINO CONNECTED WITHOUT POWER TO SECOND ARDUINO.*/

//////////////////////////////////////////// HEADERS ///////////////////////////////////////////////////////////
#include <Wire.h>                       // CLOCK // I2C
#include <DS3231.h>                     // CLOCK 
#include <LiquidCrystal.h>              // LCD 
#include <dht_nonblocking.h>            // DHT  // THINK I CAN COMMENT THIS OUT
#include "DHT.h"                        // DHT
//////////////////////////////////////////// GLOBAL VARIABLES ///////////////////////////////////////////////////////////
// CLOCK 
DS3231 clock;
RTCDateTime dt;

// PIR 
int pirLED = 13; //********************************************************CHANGE THIS ACCORDING TO THE SLAVE MASTER SETUP
int pirPin = 2;  
int pirValue;

// LCD
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // initialize the library with the numbers of the interface pins

// DHT
#define DHTPIN 4            // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11       // DHT 11
DHT dht(DHTPIN, DHTTYPE);

// I2C
#define SLAVE_ADDR 9        // Define Slave I2C Address
#define ANSWERSIZE 5        // Define Slave answer size

//////////////////////////////////////////// SETUP ///////////////////////////////////////////////////////////
void setup()
{
    // PIR 
    pinMode(pirLED, OUTPUT); // only required if 13
    pinMode(pirPin, INPUT);
    digitalWrite(pirLED, LOW);
    Serial.begin(9600);

    // CLOCK
    Serial.println("Initialize RTC module");      
    clock.begin();                                // Initialize DS3231
    
    // DHT
    Serial.println(F("DHTxx test!"));
    dht.begin();

    // LCD
    lcd.begin(16, 2);                               // LCD: set up the LCD's number of columns and rows:
    lcd.print("Hello Smart Home v1.0");                     // Print a message to the LCD.  

    // I2C
    // Initialize I2C communications as Master
    Wire.begin();
    // Setup serial monitor
    //  Serial.begin(9600);     Here listed after Wire.begin();
    Serial.println("I2C Master Demonstration");
}

//////////////////////////////////////////// LOOP ///////////////////////////////////////////////////////////
void loop()
{
    keypad();
    int time = getTime();           // CLOCK Time in seconds (can change using function below)

    static unsigned long measurement_timestamp = millis();
    if(millis() - measurement_timestamp > 1000ul)
        {
            measurement_timestamp = millis();
            if (time == 05 || time == 10 || time == 15 || time == 20 || time == 25 || time == 30 || 
                time == 35 || time == 40 || time == 45 || time == 50 || time == 55 || time == 0)
                {
                    float temp_act = readDHT(); 
                    // tempAdjust();
                }
                               // PIR
            setLCD(time);
            //delay(1000);
            // if keyIn() == true
            
            // SET LED

            int sPIR = checkPIR();  

            int night;
            if (time < 30)
                night = 0;
            else
                night = 1;
               
            // SET DESIRED TEMPERATURE
            float temp_des = 21;
            float temp_act = temp_des;        /////////////////////////////////////////////////////////// change to rely on keypad
            char heatSet;
            
            byte command;

            if (sPIR == 0)
            {
                if (temp_des >= temp_act) 
                    command = 0;
                else
                {
                    if ((temp_act - temp_des) > 0.5)
                        command = 1;
                    if ((temp_act - temp_des) > 1)
                        command = 2;
                    if ((temp_act - temp_des) > 2)
                        command = 3;
                    if ((temp_act - temp_des) > 3)
                        command = 4;
                    if ((temp_act - temp_des) > 4)
                        command = 5;
                }
            }
            else if (sPIR == 1)
            {
                if (night == 0)
                    if (temp_des >= temp_act) 
                        command = 10;
                        if ((temp_act - temp_des) > 0.5)
                            command = 11;
                        if ((temp_act - temp_des) > 1)
                            command = 12;
                        if ((temp_act - temp_des) > 2)
                            command = 13;
                        if ((temp_act - temp_des) > 3)
                            command = 14;
                        if ((temp_act - temp_des) > 4)
                            command = 15; 
                else if (night == 1)
                    if (temp_des >= temp_act) 
                        command = 20;
                        if ((temp_act - temp_des) > 0.5)
                            command = 21;
                        if ((temp_act - temp_des) > 1)
                            command = 22;
                        if ((temp_act - temp_des) > 2)
                            command = 23;
                        if ((temp_act - temp_des) > 3)
                            command = 24;
                        if ((temp_act - temp_des) > 4)
                            command = 25; 
            }

            

            // (sPIR, sRGB, sNight, heatSet)

            masterToSlave(command);
        }    
}


////////////////////////////////////////// FUNCTIONS ///////////////////////////////////////////////////////////
// CLOCK
int getTime()
{
    dt = clock.getDateTime();

  // For leading zero look to DS3231_dateformat example

    /* Serial.print("Raw data: ");
    Serial.print(dt.year);   Serial.print("-");
    Serial.print(dt.month);  Serial.print("-");
    Serial.print(dt.day);    Serial.print(" ");
    Serial.print(dt.hour);   Serial.print(":");
    Serial.print(dt.minute); Serial.print(":");
    Serial.print(dt.second); Serial.println("");
    */
    //delay(1000);
    //Serial.println(dt.second);           // CLOCK
    return (dt.second);
}


int checkPIR()
{   
    pirValue = digitalRead(pirPin);
    digitalWrite(pirLED, pirValue);

    return pirValue;
    // if (pirValue == 1)
    //     Serial.println(pirValue);
    // else if (pirValue == 0)
    //     Serial.println(pirValue);
    // else 
    //     Serial.println("No reading");
    //delay(500);
}

void setLCD(int time)
{
    // set the cursor to column 0, line 1
    // (note: line 1 is the second row, since counting begins with 0):
    //lcd.print("Hello, World!");
    lcd.setCursor(0, 1);
    // print the number of seconds since reset:
    lcd.print(time);
}    

/*
 * Poll for a measurement, keeping the state machine alive.  Returns
 * true if a measurement is available.
 */
float readDHT()
{
  //delay(2000);  
    // Wait a few seconds between measurements.
    // Reading temperature or humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    float h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    float t = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    float f = dht.readTemperature(true);
  
    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println(F("Failed to read from DHT sensor!"));
      return 0;
    }
  
    // Compute heat index in Fahrenheit (the default)
    float hif = dht.computeHeatIndex(f, h);
    // Compute heat index in Celsius (isFahreheit = false)
    float hic = dht.computeHeatIndex(t, h, false);
  
    Serial.print(F("Humidity: "));
    Serial.print(h);
    Serial.print(F("%  Temperature: "));
    Serial.print(t);
    Serial.print(F("°C "));
    //Serial.print(f);
    //Serial.print(F("°F  Heat index: "));
    Serial.print(hic);
    Serial.print(F("°C "));
    //Serial.print(hif);
    //Serial.println(F("°F"));

    return t;
}


void keypad()
{
  int keyIn;
      int keyVals [16] = {976, 450, 333, 244, 166, 138, 124, 109, 90, 81, 76, 70, 61, 57, 54, 51};
      char keys[16] = {'1','2','3','A','4','5','6','B','7','8','9','C','*','0','#','D'};
      int range = 1;
    
      keyIn = analogRead(A1);
    
      char temp = {};
    
      if (keyIn > 2)
      {
        Serial.print(keyIn);
        for(int i=0; i<=15; i++)
        {
          // The values of the keys changed, that's why the following is commented out
          //if (keyIn >= keyVals[i]-range && keyIn <= keyVals[i]+range)
          //{
          //  temp = keys[i];
          //}
        }
       Serial.print(temp);
       Serial.println("");
       delay(200);
    }
}


void masterToSlave(byte command)
{
    delay(50);
    Serial.println("Write data to slave");

        Wire.beginTransmission(SLAVE_ADDR);
        Wire.write(command);
        Wire.endTransmission();
        
    Serial.println("Receive data");
    // Read response from Slave
    // Read back 5 characters
    Wire.requestFrom(SLAVE_ADDR,ANSWERSIZE);
    
    // // Add characters to string
    // String response = "";
    // while (Wire.available()) {
    //     char b = Wire.read();
    //     response += b;
    // } 
    
    // Print to Serial Monitor
    Serial.println(command);
}

And the slave program where the error is occurring:

/*
  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");
} 
 
byte receiveEvent() {
  int x;
  // Read while data received
  while (0 < Wire.available()) {
    x = Wire.read();
    Serial.println(x);
  }
  
  // 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);
}

I know that it is expecting an int but receiving a byte. I tried changing my bytes to int, but that did not work.

I am not sure how to correct it. Could you please advise?

I think it has something to do with command?

     Wire.beginTransmission(SLAVE_ADDR);
       Wire.write(command);
       Wire.endTransmission();

I want to send bytes, but seem to be doing it incorrectly somehow? Should I convert them or write them as a string or something?

You are registering a void function_name (void) while the method of Wire class want a different type of function


void onReceive( void (*)(int) );

Check the example slave_receiver.ino included with library for how do it correctly.

1 Like

Thank you cotestatnt!

1 Like

The MasterWriter is not a good example.
I have written a few extra notes on a Arduino in Slave mode at my Wiki at Github.

Please remove the receiveEvent(); and requestEvent(); from the loop(). You need global variables to pass on data to the loop().

1 Like

Sorry for my delayed response Koepel - I've been locked down with exams. I see - thank you for the explanation and reference. I will edit my code accordingly.