-
Notifications
You must be signed in to change notification settings - Fork 121
Requesting multiple bytes: the correct way #36
Copy link
Copy link
Open
Description
Hi,
I've been spending a few days now on reading into TinyWireS, I2C protocols and standards.
After seeing the interesting discussions in different issues I do believe that TinyWireS offers support for multiple bytes to be requested by it's master. Is this correct?
I tried a million ways so far, but can't seem to get more then a single byte returned from the slave, using Wire on the Master. The code is below. If the assumption that TinyWireS is capable of handeling a master calling Wire.requestFrom(0x01, N), where am I going wrong with the code below?
Master (Arduino Uno)
/*
*
*/
#include <Wire.h>
#define I2C_MASTER_ADDR 0x04
#define I2C_SLAVE_ADDR 0x05
int pollInterval = 700;//Milliseconds
unsigned long lastPoll = 0;
void setup()
{
Wire.begin(I2C_MASTER_ADDR); // join i2c bus
Serial.begin(115200);
Serial.println("Setup complete");
}
/*
* The main loop
*/
int i = 0;
void loop()
{
//Writing to the slave
if( (millis()-lastPoll) > pollInterval)
{
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write(0x01);//Register to start at
switch(i)
{
case 0:
Wire.write(255);
Wire.write(0);
Wire.write(0);
i++;
break;
case 1:
Wire.write(0);
Wire.write(255);
Wire.write(0);
i++;
break;
case 2:
Wire.write(0);
Wire.write(0);
Wire.write(255);
i = 0;
break;
}
Wire.endTransmission();
delay(1);//Dont let the slave panic
//Set the register pointer back to 0x01, preparing for a read
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write(0x00);//Register to start at
Wire.endTransmission();
delay(1);//Dont let the slave panic
//Get values from the three registers up from 0x01
Wire.requestFrom(I2C_SLAVE_ADDR, 4);//Request N bytes
while (Wire.available())
{
uint8_t next_byte = Wire.read();
Serial.print(next_byte);Serial.print(" ");
}
Serial.println("\n");
lastPoll = millis();
}//End if time to poll again
}//End loop
Slave - ATTiny85
#include <EEPROM.h>
#include <TinyWireS.h>
#include <Bounce2.h>
#include <WS2812.h>
#ifdef __AVR__ //Which will be true for ATtiny85
#include <avr/power.h>
#endif
#define I2C_SLAVE_DEFAULT_ADDR 0x05
#define BUTTON_DEBOUNCE 5//Debounce milliseconds
#define NEOPIXEL_PIN 1
#define BUTTON_PIN 3
#define NUMPIXELS 1
/*
* I2C Registers
*
* Register map:
* 0x00 - Button state
* 0x01 - led value red
* 0x02 - led value green
* 0x03 - led value blue
*
* Total size: 4
*/
const byte reg_size = 4;
volatile uint16_t i2c_regs[reg_size];
/*
* Internal variables
*/
cRGB value;
volatile boolean led_needs_update = false;
volatile byte reg_position;
/*
* Initialize instances/classes
*/
Bounce button = Bounce();
WS2812 led(NUMPIXELS);
void setup()
{
//Start I2C
//uint8_t _device_addr = EEPROM_DATA::get_device_addr();
TinyWireS.begin(I2C_SLAVE_DEFAULT_ADDR);
TinyWireS.onReceive(i2cReceiveEvent);
TinyWireS.onRequest(i2cRequestEvent);
//Start Led
led.setOutput(NEOPIXEL_PIN);
value.b = 255; value.g = 0; value.r = 0;
led.set_crgb_at(0, value); //Set value at LED found at index 0
led.sync(); // Sends the value to the LED
//Start Button
pinMode(BUTTON_PIN, INPUT_PULLUP);
button.attach(BUTTON_PIN);
button.interval(BUTTON_DEBOUNCE);
}
void loop()
{
button.update();
if(led_needs_update)
{
led_update();
led_needs_update = false;
}
if(button.fell())
{
i2c_regs[0x00] = true;
}
if(button.rose())
{
i2c_regs[0x00] = false;
}
// This needs to be here for the TinyWireS lib
TinyWireS_stop_check();
}
/*
* I2C Handelers
*/
void i2cReceiveEvent(uint8_t howMany)
{
if (howMany < 1)
{
return;// Sanity-check
}
reg_position = TinyWireS.receive();
howMany--;
if (!howMany)
{
return;// This write was only to set the buffer for next read
}
while(howMany--)
{
//Store the recieved data in the currently selected register
i2c_regs[reg_position] = TinyWireS.receive();
//Proceed to the next register
reg_position++;
if (reg_position >= reg_size)
{
reg_position = 0;
}
}
led_needs_update = true;
}//End i2cReceiveEvent()
void i2cRequestEvent()
{
//Send the value on the current register position
TinyWireS.send(i2c_regs[reg_position]);
//WORKAROUND -> send all bytes, starting from the current registers
/*int n = reg_size - reg_position;//Number of registers to return
for(int i = reg_position; i < n; i++)
{//Return all bytes from the reg_position to the end
TinyWireS.send(i2c_regs[i]);
}*/
// Increment the reg position on each read, and loop back to zero
reg_position++;
if (reg_position >= reg_size)
{
reg_position = 0;
}
}//End i2cRequestEvent
/*
* Helper functions
*/
void led_update()
{
cRGB val;
val.r = i2c_regs[0x01];
val.g = i2c_regs[0x02];
val.b = i2c_regs[0x03];
led.set_crgb_at(0, val);
led.sync(); // Sends the value to the LED
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels