Hi there!
Im building a little i2c device with an ATTIny85.
I want to read an analog value from a photoresistor (later a battery reading) and transfer it via i2c to a master device. I connected the photoresitor on the tiny physical pin 2 so it should be "A3" in the IDE.
If I transfer the bytes like this:
// Fill the register buffer
int val = 512;
byte buf[2];
uInt16ToBytes(val, buf);
REGISTERS[REG_BATTERYL] = buf[0];
REGISTERS[REG_BATTERYH] = buf[1];
void uInt16ToBytes(uint16_t integer, byte *buf)
{
buf[0] = integer >> 8;
buf[1] = integer;
}
void requestEvent()
{
TinyWireS.send(REGISTERS[REGISTER_POINTER]);
REGISTER_POINTER++;
if (REGISTER_POINTER >= REGISTER_SIZE)
{
REGISTER_POINTER = 0;
}
}
Everything works just fine. The bytes are transfered and the int value gets printed on my master device. So it must be the analogRead somehow. The circuit is fine since if I read it on the UNO I get correct values according to the environment light.
BUT if I do it like this:
// Fill the register buffer
int val = analogRead(PIN_BATTERY);
byte buf[2];
uInt16ToBytes(val, buf);
REGISTERS[REG_BATTERYL] = buf[0];
REGISTERS[REG_BATTERYH] = buf[1];
The bytes allways return 0 and therefore an int of 0.
The full code is here:
#include <TinyWireS.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
// ---------------------------------------------------------------
// CONSTANTS -----------------------------------------------------
// ---------------------------------------------------------------
#define PIN_POWER PB4
#define PIN_BATTERY A3
#define PIN_ERROR PB1
#define I2C_ADDRESS 0x13
#define MODE_WRITE 0x50
#define MODE_READ 0x51
#define REG_SETTINGS 0x00
#define REG_POWER 0x01
#define REG_SLEEPTIMER 0x02
#define REG_ONTIMER 0x03
#define REG_BATTERYL 0x04
#define REG_BATTERYH 0x05
#define REGISTER_SIZE 6
byte REGISTERS[] =
{
0x01, // RSETT, General purpose register (Bit 0 = Power Pin, Bit 1 = Auto sleep, Bit 2 = N/A etc.)
0x01, // PWRRG, Power register
0x02, // SLDUR, Sleep duration 8x2 = 16Sec
0x10, // ONTMR, On timer, 0 = unlimited (Turn off via power bit)
0x00, // BATTR, Battery level low byte
0x00, // BATTR, Battery level high byte
};
// ---------------------------------------------------------------
// VARIABLES -----------------------------------------------------
// ---------------------------------------------------------------
byte I2C_MODE = MODE_READ;
byte REGISTER_POINTER = REG_POWER;
uint8_t timer = 2; //10min // 8x2=16 10min = 600 Sek = 600 / 8 = 75
volatile boolean on = true;
uint8_t currentTimer = 0;
byte i2cBuffer[4];
// ---------------------------------------------------------------
// SETUP ---------------------------------------------------------
// ---------------------------------------------------------------
void setup()
{
pinMode(PIN_POWER, OUTPUT);
pinMode(PIN_BATTERY, INPUT);
TinyWireS.begin(I2C_ADDRESS);
TinyWireS.onRequest(requestEvent);
TinyWireS.onReceive(recieveEvent);
}
// ---------------------------------------------------------------
// LOOP ----------------------------------------------------------
// ---------------------------------------------------------------
void loop()
{
if(currentTimer < timer-1)
{
currentTimer++;
} else {
tws_delay(10000);
currentTimer = 0;
}
watchdogSleep();
TinyWireS_stop_check();
}
void enablePowerPin()
{
digitalWrite (PIN_POWER, 1);
tws_delay(10000);
digitalWrite (PIN_POWER, 0);
}
void blinky(byte count, int speed)
{
for(int i=0; i<count;i++)
{
digitalWrite (PIN_POWER, 1);
tws_delay(speed);
digitalWrite (PIN_POWER, 0);
tws_delay(speed);
}
}
// ---------------------------------------------------------------
// I2C -----------------------------------------------------------
// ---------------------------------------------------------------
void recieveEvent(uint8_t byteCount)
{
// Sanity check
if(byteCount < 1 || byteCount > 4)
{
return;
}
// Transfer recieved bytes into local I2C buffer
for(int i = 0; i<byteCount; i++)
{
i2cBuffer[i] = TinyWireS.receive();
}
handleI2CCommand();
clearI2CBuffer();
}
void handleI2CCommand()
{
switch(i2cBuffer[0])
{
case MODE_WRITE:
switch(i2cBuffer[1])
{
case REG_POWER:
REGISTERS[REG_POWER] = i2cBuffer[2];
digitalWrite (PIN_POWER, bitRead(REGISTERS[REG_POWER],0));
digitalWrite (PIN_ERROR, bitRead(REGISTERS[REG_POWER],1));
break;
case REG_SLEEPTIMER:
break;
}
break;
case MODE_READ:
REGISTER_POINTER = i2cBuffer[1];
switch(i2cBuffer[1])
{
case REG_BATTERYL:
int batteryValue = analogRead(PIN_BATTERY);
byte buf[2];
uInt16ToBytes(batteryValue, buf);
REGISTERS[REG_BATTERYL] = buf[0];
REGISTERS[REG_BATTERYH] = buf[1];
break;
}
break;
}
}
void uInt16ToBytes(uint16_t integer, byte *buf)
{
buf[0] = integer >> 8;
buf[1] = integer;
}
void clearI2CBuffer()
{
for(int i = 0; i<4; i++)
{
i2cBuffer[i] = 0;
}
}
void requestEvent()
{
TinyWireS.send(REGISTERS[REGISTER_POINTER]);
REGISTER_POINTER++;
if (REGISTER_POINTER >= REGISTER_SIZE)
{
REGISTER_POINTER = 0;
}
}
// ---------------------------------------------------------------
// WATCHDOG ------------------------------------------------------
// ---------------------------------------------------------------
void watchdogSleep()
{
//myWatchdogEnable (0b10001);
if (WDTCR&1<<WDIE)
{ //still waiting for WDT interrupts, simply go sleep
sleep_bod_disable();
sleep_mode();
} else {
//WDT interrupt is disabled (from WDT ISR)
myWatchdogEnable (0b100001); // 8 second
}
}
ISR(WDT_vect)
{
on = !on;
wdt_disable();
}
// sleep bit patterns:
// 1 second: 0b000110
// 2 seconds: 0b000111
// 4 seconds: 0b100000
// 8 seconds: 0b100001
void myWatchdogEnable(const byte interval)
{
noInterrupts();
wdt_reset();
MCUSR = 0; // reset various flags
WDTCR |= 0b00011000; // see docs, set WDCE, WDE
WDTCR = 0b01000110 | interval; // set WDIE, and appropriate delay
ADCSRA &= ~_BV(ADEN);
set_sleep_mode (SLEEP_MODE_PWR_DOWN); //SLEEP_MODE_PWR_DOWN, SLEEP_MODE_IDLE
sleep_bod_disable();
interrupts();
sleep_mode();
}
Thanks for your time and help!