RPM_4_dig_disp_interrupt_easytransfer_library_problem

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++;
}

  if (millis() - lastmillis == 1000)

Expecting the difference to be EXACTLY 1000 is a mistake. The test should be for the difference being greater than or equal 1000 (>=).

…apparently attachInterupt fuction doesnt work over Wire()

I don’t know what you are trying to say here. attachInterrupt() defines an interrupt handler to call under specific conditions. The onReceive() and onRequest() methods of the Wire class are also interrupt handlers. When an interrupt handler is running, other interrupts are disabled.

Is there trick witch i couldn’t find and i miss it?

No, you do not want to re-enable interrupts in an interrupt handler. Trust me.

Instead of posting 40-eleven pieces of code, and saying some of this works and some doesn’t, post JUST the master code and the slave code that you are trying to get to work together.

Explain what each actually does and what each doesn’t do. Then, we can tell you what you have to do to get them to play well together.

PaulS:

if (millis() - lastmillis == 1000)

Expecting the difference to be EXACTLY 1000 is a mistake. The test should be for the difference being greater than or equal 1000 (>=).

Wow. i was in the dead end, this is solution. Thx. Now i coud display RPM on the screen without problem.

PaulS:
Instead of posting 40-eleven pieces of code, and saying some of this works and some doesn't, post JUST the master code and the slave code that you are trying to get to work together.

Explain what each actually does and what each doesn't do. Then, we can tell you what you have to do to get them to play well together.

Sorry noted. I m new on the forum so i think that it could be better to explain what works and it doesnt. I believe more info are better than less.

But anyway i think this should work for now.