Hello,
I've run into a bit of a problem; I would like to send nine bytes of information from an Attiny84 to an Atmega1284 via I2C.
I'm aware that Attinies can only send one byte at a time, but surely there has to be a way of sending several bytes in a row from an Attiny to an Atmega via I2C?
Here is my Attiny sketch in its entirety:
/*--------------------------------------------------------------------------------------------------------------------
CarDuino Convenience Module Sketch
This sketch monitors a variety of functions:
- Outside and inside air temperature, using two DS18B20 sensors
- Windscreen wash level; a lead inside the windscreen wash pump goes to GND when
windscreen wash is low. This lead is connected to Attiny pin 10 in this sketch.
- lamp check modules; these monitor headlamps, taillights and brake lights.
If faults are present at either pairs of lights, a particular signal pin
on the lamp check units will go high to +12V. This signal is then
fed into the Attiny84 using a 22K/10K voltage divider to generate
a logic HIGH.
This data is then sent over to the head unit module via I2C
where it is displayed on the screen.
*/
#include <TinyWireS.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "SoftwareSerial.h"
// -------------------------------- Pin definitions; note CLOCKWISE pin assignment!
// status LED
#define led A0
// Serial connection... working without a problem
const byte rx = A2;
const byte tx = A3;
SoftwareSerial mySerial(rx, tx);
// lamp check pins...
#define kb 5 //brake lights
#define ksb 7 //taillights
#define ksf 8 //headlamps
//DS18B20 temperature sensor pin
#define TempSensors 9
OneWire oneWire(TempSensors);
DallasTemperature sensors(&oneWire);
// windscreen wash pin
#define windscreenWash 10
//temperature sensor variables
volatile byte* outsideTempFloatPtr;
volatile byte* insideTempFloatPtr;
volatile float outsideTemp;
volatile float insideTemp;
// lamp check and windscreen wash info
byte errorStatus;
unsigned long serialStart = 0;
unsigned long ledStart = 0;
void setup() {
mySerial.begin(115200);
sensors.begin(); // Begin temperature sensors
TinyWireS.begin(3); // join i2c bus with address #3
TinyWireS.onRequest(requestEvent); // register event
pinMode (windscreenWash, INPUT);
pinMode (led, OUTPUT);
pinMode(ksf, INPUT);
pinMode(ksb, INPUT);
pinMode(kb, INPUT);
pinMode(rx, INPUT);
pinMode(tx, OUTPUT);
digitalWrite(led, HIGH);
}
void loop() {
if (millis() - ledStart >= 250) digitalWrite(led, HIGH);
//--------------------------------------------------------------------------------------------------------------------
// -------------------------------- Gathering data
// Outside and Inside Temperatures
sensors.requestTemperatures();
outsideTemp = sensors.getTempCByIndex(0);
insideTemp = sensors.getTempCByIndex(1);
// Windscreen Washer Level
//windscreenWashError = digitalRead(windscreenWash);
// Front Lamp Check Module
errorStatus = digitalRead(ksf) <<0 | (digitalRead(ksb) << 1) | ( digitalRead(kb) << 2) | (digitalRead(windscreenWash) << 3);
if (!serialStart) serialStart = millis();
if (millis() - serialStart >= 2000) {
mySerial.println(outsideTemp);
mySerial.println(insideTemp);
mySerial.println(errorStatus, BIN);
mySerial.print("\n\n");
serialStart = 0;
}
}
void requestEvent() {
// -------------------------------- I2C Request Event Definition
digitalWrite(led, LOW);
ledStart = millis();
// send nine bytes
byte sendData[9];
// processing temperature sensor data
// Outside
outsideTempFloatPtr = (byte*) & outsideTemp;
sendData[0] = outsideTempFloatPtr[0];
sendData[1] = outsideTempFloatPtr[1];
sendData[2] = outsideTempFloatPtr[2];
sendData[3] = outsideTempFloatPtr[3];
// Inside
insideTempFloatPtr = (byte*) & insideTemp;
sendData[4] = insideTempFloatPtr[0];
sendData[5] = insideTempFloatPtr[1];
sendData[6] = insideTempFloatPtr[2];
sendData[7] = insideTempFloatPtr[3];
// windscreen wash liquid level
sendData[8] = errorStatus;
for (int i = 0; i <= 8; i++) TinyWireS.send(sendData[i]);
}
tl;dr: This is the bit where I try to send my data:
for (int i = 0; i <= 8; i++) TinyWireS.send(sendData[i]);
Is this the wrong way to do it? What happens is that when the ISR is called, the LED goes LOW, as it should according to my code. So the I2C connection itself looks like it's working in principle. But then the LED just stays low and I get a read error on the other end, at the Atmega. So effectively I guess no data is transferred. It kind of seems like the Attiny crashes on the request event, because the serial monitor then also goes dead, i.e. no more updates as implemented in my code.
Any help is appreciated.
