Hi!
In short i wanna display RPM figures on the 4digit 7 segment display usig 2 ardurinos UNO.
Config;
-Master receive slave data and displays on the LED display.
-Slave read proximity sensor data and sends to master.
-All is connected via I2C connection with twisted pair cables.
-For I2C I use EASYTRANSFER library.
1.Step
So before i jump on the boat on the problem. I i made sanity check in this “step 1”.
Here i manage to connect Master Code and show number on LCD successfully.
That means i prepare Slave to send Master photocell analog readouts data (so no RPM there jet).
/*Master Reader LCD steP V1M
*
* bazira na EasyTrans library
*/
//za potrebe LCD
const int digitPins[4] = {
4,5,6,7}; //4 common anode pins of the display
const int clockPin = 10; //74HC595 Pin 10
const int latchPin = 11; //74HC595 Pin 11
const int dataPin = 12; //74HC595 Pin 12
const byte digit[10] = //seven segment digits in bits
{
B00111111, //0
B00000110, //1
B01011011, //2
B01001111, //3
B01100110, //4
B01101101, //5
B01111101, //6
B00000111, //7
B01111111, //8
B01101111 //9
};
volatile int digitBuffer[4] = {
0};
int digitScan = 0, flag=0, soft_scaler = 0;
//za potrebe prenos z I2C protokolom
#include <Wire.h>
#include <EasyTransferI2C.h>
volatile int c;
int varNumber;
//create object
EasyTransferI2C ET;
struct RECEIVE_DATA_STRUCTURE{
//put your variable definitions here for the data you want to receive
//THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
int varNumber;
};
//give a name to the group of data
RECEIVE_DATA_STRUCTURE mydata;
//define slave i2c address
#define I2C_SLAVE_ADDRESS 9
void setup(){
Serial.begin(9600); // start serial for output
for(int i=0;i<4;i++)
{
pinMode(digitPins[i],OUTPUT);
}
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
Wire.begin(I2C_SLAVE_ADDRESS);
//start the library, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc.
ET.begin(details(mydata),&Wire);
//define handler function on receiving data
Wire.onReceive(receive);
}
void updateBuffer(){
digitBuffer[3] = int(c)/1000;
digitBuffer[2] = (int(c)%1000)/100;
digitBuffer[1] = (int(c)%100)/10;
digitBuffer[0] = (int(c)%100)%10;
updateDisp();
}
void updateDisp(){
for(byte j=0; j<4; j++)
digitalWrite(digitPins[j], LOW);
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, B11111111);
digitalWrite(latchPin, HIGH);
delayMicroseconds(100);
digitalWrite(digitPins[digitScan], HIGH);
digitalWrite(latchPin, LOW);
if(digitScan==2)//change1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
shiftOut(dataPin, clockPin, MSBFIRST, ~(digit[digitBuffer[digitScan]] | B10000000)); //print the decimal point on the 3rd digit
else
shiftOut(dataPin, clockPin, MSBFIRST, ~digit[digitBuffer[digitScan]]);
digitalWrite(latchPin, HIGH);
digitScan++;
if(digitScan>3) digitScan=0;
}
void loop() {
//check and see if a data packet has come in.
if(ET.receiveData()){
//this is how you access the variables. [name of the group].[variable name]
//since we have data, we will blink it out.
c = mydata.varNumber;
Serial.print("c = ");
Serial.println(c);
updateBuffer();
delay(3);
}else{
updateBuffer();
delay(3);
}
}
void receive(int numBytes) {}//pisal je numBytes
/*Slave sender LCD variable number z uporabo photocellice analog read
* bazira na EasyTrans library
*/
int varNumber;
int photoPin = A0;
#include <Wire.h>
#include <EasyTransferI2C.h>
//create object
EasyTransferI2C ET;
struct SEND_DATA_STRUCTURE{
//put your variable definitions here for the data you want to send
//THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
int varNumber;
};
//give a name to the group of data
SEND_DATA_STRUCTURE mydata;
//define slave i2c address
#define I2C_SLAVE_ADDRESS 9
int number = 1;
void setup(){
Wire.begin();
Serial.begin(9600);
//start the library, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc.
ET.begin(details(mydata),&Wire);
}
void loop(){
//this is how you access the variables. [name of the group].[variable name]
//number++;/**36;*/
mydata.varNumber = analogRead(photoPin);
//send the data
ET.sendData(I2C_SLAVE_ADDRESS);
Serial.print("photoValue = ");
Serial.println(analogRead(photoPin));
delay(500);
}
2. PROBLEMATIC STEP 2
But problem is in the next step. In this step 2 when i try use…
-millis()
-attachinterupt() on pin 0 (that is on UNO 2)
…apparently attachInterupt fuction doesnt work over Wire() and ET.easytransferInteruppt()?
Is there trick witch i couldn’t find and i miss it?
Master code is same as is from STEP 1 (above; i think receive variables should works)
/*Slave sender LCD RPM read
* bazira na EasyTrans library
*/
int varNumber;
volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatile
int rpm = 0;
unsigned long lastmillis = 0;
#include <Wire.h>
#include <EasyTransferI2C.h>
//create object
EasyTransferI2C ET;
struct SEND_DATA_STRUCTURE{
//put your variable definitions here for the data you want to send
//THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
int varNumber;
};
//give a name to the group of data
SEND_DATA_STRUCTURE mydata;
//define slave i2c address
#define I2C_SLAVE_ADDRESS 9
void setup(){
Wire.begin();
//Serial.begin(9600);
//start the library, pass in the data details and the name of the serial port. Can be Serial, Serial1, Serial2, etc.
ET.begin(details(mydata),&Wire);
attachInterrupt(0, rpm_fan, FALLING);//interrupt cero (0) is on pin two(2).
}
void loop(){
if (millis() - lastmillis == 1000){ /*Uptade every one second, this will be equal to reading frecuency (Hz). dodan >= !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
detachInterrupt(0); //Disable interrupt when calculating
rpm = rpmcount * 60; /* Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
/* Serial.print("RPM =\t"); //print the word "RPM" and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word "Hz".
Serial.println(rpmcount); //print revolutions per second or Hz. And print new line or enter.*/
//this is how you access the variables. [name of the group].[variable name]
mydata.varNumber = rpm;
//send the data
ET.sendData(I2C_SLAVE_ADDRESS);
rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Uptade lasmillis
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
}
delay(100);
}
void rpm_fan(){ /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
rpmcount++;
}
Rpm code also work individually. That way i check wiring that means i made CODE without data sending over I2c just normal serial output. That is fine.
void loop(){
if (millis() - lastmillis == 1000){ /*Uptade every one second, this will be equal to reading frecuency (Hz). dodan >= !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
detachInterrupt(0); //Disable interrupt when calculating
rpm = rpmcount * 60; /* Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
Serial.print("RPM =\t"); //print the word "RPM" and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word "Hz".
Serial.println(rpmcount); /*print revolutions per second or Hz. And print new line or enter.*/
rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Uptade lasmillis
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
}
}
void rpm_fan(){ /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
rpmcount++;
}