Hello, I am trying to set up communication between multiple AT-Tiny devices (slaves) and an ESP32 (master.) The AT-Tiny controls a motor and reads its own I2C encoder (using a separate software I2C bus.) I have successfully gotten 2-way communication working when a single device is connected, however when multiple are connected and I attempt to send motor commands from the master to the slave, the data sent from the AT-Tiny breaks. The data values are usually between 0-10,000 however, when I send motor commands the values are in the millions and are very random. I have no idea what the problem is so any ideas would be very much appreciated.
Master
#include <Wire.h>
union Buffer
{
long longNumber;
byte longBytes[4];
};
//send
byte target[5];
//receive
byte motorPos[5];
int32_t encoder[5];
void setup()
{
Serial.begin(38400);
Wire.begin();
}
void loop()
{
for (int i = 1; i < 6; i++)
{
setTarget(i, target[i - 1]);
requestData(i);
}
for (int i = 0; i < 4; i++)
{
Serial.print(encoder[i]);
Serial.print(", ");
}
Serial.println(encoder[4]);
if (Serial.available() > 0)
target[0] = Serial.readString().toInt();
}
void requestData(int ADDRESS)
{
Buffer buffer;
Wire.requestFrom(ADDRESS, 5); // request bytes from slave device #8
if (Wire.available() > 4) // slave may send less than requested
{
for (int i = 0; i < 4; i++)
buffer.longBytes[i] = Wire.read();
motorPos[ADDRESS - 1] = Wire.read();
encoder[ADDRESS - 1] = (int32_t)buffer.longNumber;
}
}
void setTarget(int ADDRESS, byte pos)
{
int data = pos + 3;
Wire.beginTransmission(ADDRESS);
Wire.write(data);
Wire.endTransmission();
}
Slave
#define F_CPU 8000000 // clock speed: 8MHz (internal crystal)
#define SLAVE_ADRESS 0x05 //Device adress: 0x08
#include "TinyWireS.h" // I2C library for ATtiny84A (and other older ATtinys)
#include <avr/interrupt.h>
AS5600 dEncoder;
const int
m1 = PA2,
m2 = PA3,
aEncoder = PA1;
volatile byte motorPos;
volatile byte targetPos;
long revolutions = 0; // number of revolutions the encoder has made
double position = 0; // the calculated value the encoder is at
double output; // raw value from AS5600
long lastOutput; // last output from AS5600
union Buffer
{
long longNumber;
byte longBytes[4];
};
Buffer buffer; // create an instance of Buffer
void setup()
{
pinMode(m1, OUTPUT);
pinMode(m2, OUTPUT);
pinMode(aEncoder, INPUT);
TinyWireS.begin(SLAVE_ADRESS);
TinyWireS.onRequest(requestEvent);
TinyWireS.onReceive(receiveEvent);
output = dEncoder.getPosition();
lastOutput = output;
position = output;
targetPos = -1;
cli();
PCMSK0 |= (1 << aEncoder);
GIMSK |= (1 << PCIE0);
sei();
}
void loop()
{
output = dEncoder.getPosition(); // get the raw value of the encoder
if ((lastOutput - output) > 2047 ) // check if a full rotation has been made
revolutions++;
if ((lastOutput - output) < -2047 )
revolutions--;
position = revolutions * 4096 + output; // calculate the position the the encoder is at based off of the number of revolutions
buffer.longNumber = position;
lastOutput = output; // save the last raw value for the next loop
if (targetPos > -1)
{
if (motorPos > targetPos)
reverse();
else if (motorPos < targetPos)
forward();
else brake();
}
}
volatile bool spin;
unsigned long lastInterrupt;
ISR(PCINT0_vect)
{
if (millis() - lastInterrupt > 1)
{
lastInterrupt = millis();
if (spin)
motorPos++;
else motorPos--;
}
return;
}
void requestEvent()
{
for (int i = 0; i < 4; i++)
TinyWireS.write(buffer.longBytes[i]); // send requested bytes
TinyWireS.write(motorPos);
}
void receiveEvent()
{
byte mState; //0 reverse, 1 = brake, 2 = forwards
if (TinyWireS.available() > 0) // slave may send less than requested
mState = TinyWireS.read(); // read motor state
if (mState > 2)
targetPos = mState - 3;
else
{
targetPos = -1;
if (mState == 0)
reverse();
if (mState == 1)
brake();
if (mState == 2)
forward();
}
}