Hi Arduino Community
I hope you can help me, Im stuck and i don't know what I've done! Maybe it will stand out to you where I have gone wrong?
I had a tacho working perfectly on an ATTiny45, using the TinyWire.h library.
I was reading it with the standard wire library and getting back RPM values that I had validated as perfect with an external tacho.
I have 32 teeth on an encoder wheel connected to a generator which interrupt an led and light sensitive diode. Its one of those modules pre packaged to stand off each other so you can run an interruption between like an encoder wheel.
The output also runs through a SN74LS14 HEX SCHMITT-TRIGGER INVERTER chip to help ensure nice square pulses without bouncing
The output from my master reader last week read something like:
LowByte, HighByte, RPMValue
0, 11, 11
0, 22, 22
0, 15, 15
0, 7, 7
However now it reads:
0, 11, 2816
0, 22, 5632
0, 15, 3840
0, 7, 1792
The third value supposedly being the integer representation of my RPM, however 0 high byte + 11 low byte I think should be and 11 not a 2816
And I don't think I changed anything! I even took old copies back from time machine and they look identical!
Clearly I have changed something and I barely understood the code to begin with so Ive been back over the sources and even started from scratch but I cant get the correct values back again:(
I have no idea where these big values are coming from, is it in the rejoining of the bytes that the code is incorrect?
Slave / Tinywire.h on At Tiny
/* AT Tiny RPM Encode
* Ben Harper April 2014
* LED on digital pin 3 (ATtiny Pin 2)
* IR Encoder input onto digital pin 4 (ATtiny Pin 3)
*
________
(PCINT5/RESET/ADC0/dW) PB5 - 1| |8 - VCC
(PCINT3/XTAL1/CLKI/OC1B/ADC3) PB3 - 2| AT |7 - PB2 (SCK/USCK/SCL/ADC1/T0/INT0/PCINT2)
PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4 - 3| TINY |6 - PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1)
GND - 4| 45/85 |5 - 5PB0 (MOSI/DI/SDA/AIN0/OC0A/OC1A/AREF/PCINT0)
--------
In Arduino Terminology:
AT45Pin1 = Arduino's Reset
AT45Pin2 = Arduino's Digital 3 & Analog 3
AT45Pin3 = Arduino's Digital 4 & Analog 2
AT45Pin4 = Arduino's Gnd
AT45Pin5 = Arduino's Digital 0 (PWM) & MOSI
AT45Pin6 = Arduino's Digital 1 (PWM) & MISO
AT45Pin7 = Arduino's Digital 2 & Analog 1 & SCK
AT45Pin8 = Arduino's VCC
Good Info For ATTiny45 With Arduino: http://highlowtech.org/?p=1695
*/
#include "TinyWireS.h" //For I2C on ATTiny's
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
#define I2C_SLAVE_ADDRESS 0x4 // Address of this device as an I2C slave
int pinLed = 3; //Led to show encoder is reading. toggles on and off every interupt (removed this functionality)
int EncoderPin = 4; //Tacho TTL input - Connected to IR Encoder Sensor
volatile int pulses; //Integer to count Encoder Pulses
unsigned long currentTime;
unsigned long loopTime;
int RPM = 0;
//boolean changed = true;
boolean firstbyte = true;
byte lowByte;
byte highByte;
void setup(){
//pinMode(pinLed,OUTPUT);
pinMode(4,INPUT);
sbi(IMSK,PCIE); // Turn on Pin Change interrupt
sbi(PCMSK,PCINT4); //Specify Which pins are affected by the interrupt
TinyWireS.begin(I2C_SLAVE_ADDRESS); // join i2c network
TinyWireS.onRequest(requestEvent); // Sets Functional to call on I2C request
}
void loop()
{
currentTime = millis();
if(currentTime >= (loopTime + 500)){
loopTime = currentTime; // Updates loopTime
// RPM = pulses*120/4/32; //.5 Second upadtes *120 to get up to 60seconds, /32 ridges in encoder, /4 ticks per ridge
//or simplified = *.9375
RPM = pulses*.9375;
pulses=0;
}
TinyWireS_stop_check(); //Not Sure what this does but Tiny I2C doesnt seem to like not having it
}
ISR(PCINT0_vect) {
pulses++;
//digitalWrite(pinLed,!digitalRead(pinLed));
}
void requestEvent()
{
if(firstbyte == true){ // on the first byte we do the math
lowByte = (byte) (RPM & 0xff);
highByte = (byte) ((RPM >> 8) & 0xff);
firstbyte = false; //so next time though we send the next byte
TinyWireS.send(lowByte);
}
else {
TinyWireS.send(highByte);
firstbyte = true;
}
}
Master Reader on Mega2560
#include <Wire.h>
volatile int value =0;
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
Serial.println("begin:");
}
void loop()
{
byte hb;
byte lb;
Wire.requestFrom(4,1);
if (Wire.available()) {
// hb=Wire.read();
lb=Wire.read();
}
Wire.requestFrom(4,1);
if (Wire.available()) {
hb=Wire.read();
}
value = ((hb<<8)+lb);
Serial.print(lb);
Serial.print(", ");
Serial.print(hb);
Serial.print(", ");
Serial.println (value);
delay(1000);
}
Ill admit I have been playing with the code, I need to use a separate line for the ATTiny Slave as I have 4 other i2C native chips on the I2C line as well and for some reason the ATTiny doesnt play well with the others. I found I could use softi2c to get around it and hopefully come back to solve this problem later. But I should see why my current situation no longer works before trying to port over to SoftI2c as a master. I failed to understand how to use the softI2c so far as it seems to need to ask for data from a specific address and I dont know how to code that in the Attiny slaves TinyWire library. Not to fussed about working that out this minute but just to admit that I may have changed something and that be the reason its all broke!
Ive gotten by for months learning Arduino and AVR and associated electronic theory just reading previous posts without having to bother anyone but I just need fresh eyes here because I am stumped!
Cheers if you can give me any pointers, or for just reading this far!
Benny