Button Issues over i2c

Can someone explain how to get this character string to send over i2c in the Wire.write. It gives me the error "no matching function for call to 'I2CDriverWire::write(StringSumHelper&)". I am trying to send button status over i2c. Basically when I click a button, it serial prints bt5: 1 for pressed and when I release the button it sends bt5: 0 for released. I'm trying to send this info over i2c

#include <i2c_device.h>
#include <i2c_driver.h>
#include <i2c_driver_wire.h>
#include "i2c_register_slave.h"



int nbts[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 26};
int startpin = 0;
int bts[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 26};
boolean btgs[24];


void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 24; i++) bts[i] = nbts[i];
  for (int i = 0; i < 24; i++) btgs[i] = false;
  for (int i = 0; i < 24; i++) pinMode(bts[i], INPUT_PULLUP);
  Wire.begin(1);
  //  Wire.onRequest(requestEvent);
}

void loop() {
  for (int i = 0; i < 24; i++) {
    if (!btgs[i]) {
      if (digitalRead(bts[i]) == LOW) {
        Serial.print("bt" + String(i) + ":");
        Serial.println(1);
        btgs[i] = true;
      }
    }
    else {
      if (digitalRead(bts[i]) == HIGH) {
        Serial.print("bt" + String(i) + ":");
        Serial.println(0);
        btgs[i] = false;
      }
    }
  }
}
void requestEvent() {
  for (int i = 0; i < 24; i++) {
    if (!btgs[i]) {
      if (digitalRead(bts[i]) == LOW) {
        Wire.write("bt" + String(i) + ":");
        Wire.write(1);
        btgs[i] = true;
      }
    }
    else {
      if (digitalRead(bts[i]) == HIGH) {
        Wire.write("bt" + String(i) + ":");
        Wire.write(0);
        btgs[i] = false;
      }
    }
  }
  delay(15);
}

In i2c_driver_wire.h I only see the following declarations for the write method:

   size_t write(uint8_t data) override;
   size_t write(const uint8_t* data, size_t length) override;

You could use the 2nd definition of write by creating a uint8_t buffer with the string data and writing it as a buffer of bytes.

Ok, how do I include that into the code. This a teensy 4.0 which is the wire.h library is not included.

Also is there an alternative to the String class that I can use in my specific code?

#include <i2c_device.h>
#include <i2c_driver.h>
#include <i2c_driver_wire.h>
#include "i2c_register_slave.h"



int nbts[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 26};
int startpin = 0;
int bts[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 26};
boolean btgs[24];
String a = String();
int myArray[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 26};



void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 24; i++) bts[i] = nbts[i];
  for (int i = 0; i < 24; i++) btgs[i] = false;
  for (int i = 0; i < 24; i++) pinMode(bts[i], INPUT_PULLUP);
  Wire.begin(1);
  Wire.onRequest(requestEvent);
}

void loop() {
  for (int i = 0; i < 24; i++) {
    if (!btgs[i]) {
      if (digitalRead(bts[i]) == LOW) {
        Serial.print("bt");
        Serial.print(nbts[i]);
        Serial.print(":");
        Serial.println(1);
        btgs[i] = true;
      }
    }
    else {
      if (digitalRead(bts[i]) == HIGH) {
        Serial.print("bt");
        Serial.print(nbts[i]);
        Serial.print(":");
        Serial.println(0);
        btgs[i] = false;
      }
    }
  }
}
void requestEvent() {
  for (int i = 0; i < 24; i++) {
    if (!btgs[i]) {
      if (digitalRead(bts[i]) == LOW) {
        Wire.write("bt");
        Wire.write(nbts[i]);
        Wire.write(":");
        Wire.write(1);
        btgs[i] = true;
      }
    }
    else {
      if (digitalRead(bts[i]) == HIGH) {
        Wire.write("bt");
        Wire.write(nbts[i]);
        Wire.write(":");
        Wire.write(0);
        btgs[i] = false;
      }
    }
  }
  delay(5);
}

Fixed the code I think. How do I make it so that the master reads the data just as its printed.
That way I can perhaps make a code that says if bt1=0 enable button 1 or digitalwrite pin 1.

Nope. I suspect this will not transmit what you think it does. I can detail why not if you like. Again the write method only supports transmitting a byte or a buffer of bytes. If you want to transmit everything in ASCII then the quick and dirty way would be this. I am unable to test this:

        char xmitString[10];
        sprintf(xmitString, "bt%d:1", nbts[i]);
        Wire.write((const uint8_t*) xmitString, strlen(xmitString));   transmit ASCII string

If you transmit it as I have shown then it will read it just as it is printed. Transmitting in ASCII is not efficient (6 bytes in this case). You could transmit the pin number and status in binary with only 2 bytes (actually only 1 byte if you use a single bit for the status and the other 7 for the pin number).

1 Like

Ok if you have time. Can you explain and you’ve been really helpful. I’ll give the code a shot and I’m not fully understanding the binary. I know binary transmits in the form of 1 and 0. Do I take that binary code and translate it back to ascii in the master sketch?

No. Not if you transmit it the way I proposed and read it into a character array and then print it (making sure you null terminate it).

Everything is stored, transmits, etc. in 1s and 0s. Processors operate on binary data. It just depends on how that data is interpreted. For example, let's say you have a byte of data and it is equal to 48 decimal (which also equals 30 hex, and 00110000 binary). If you interpret it as an integer then it is just that, 48. If you interpret it as ASCII then it equals the character '0'. Get it? That is why you have to tell the compiler the type of data a variable is. Therefore when you go to print that byte of data, if you have defined it as a character it will print as '0'. If you have defined it as an integer it will typically print it as 48 (base 10, decimal) if you don't specify the number base. If you print it and specify base 16 (hex) then it will print 30. If you print it and specify base 2 (binary) then it will print 110000. However, it is the same value stored in RAM.

Ok, I had a generic code on the arduino and it read all 0 at took one button press and nothing worked after that. I overwritten that code with a generic one and can't get it to read at all. I've tried the Serial.read commands but I think that has to do only serial monitor inputs. I've also tried the Wire.readBytes and that doesn't seem to work. Could you explain how I might go about writing a master sketch? Basically when the button 5 is pressed it shows bt5:1 and then when released it shows bt5:0. I'm at a loss with I2C and pretty much done.

Post both codes. Perhaps you have a wiring issue? I would concentrate on very simple master and slave sketches (transmit and receive a sequence of hard-coded values) to verify the hardware connections. Otherwise you are just wasting your time with the rest of it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.