Dear All , i would like to create function that sends data over nRF24 to raspberry pi and if arduino receive answer then counter will be 0. Everything works good but .. if i have turned off program on raspberry , arduino take a loop and program suspends.
I have something wrong with procedure while .. i know. I would like to create comething like timeout, if for examle for 5 sec arduino didn't receive ansewer then it will try to send and reveive data again. Please help. Below my ugly code of sending function ;).
bool sendOverRadio() {
radio.powerUp();
uint16_t nodeID = pipes[0] & 0xff;
char outBuffer[32]="Something to Send";
char inBuffer[32]= "";
int SendLoop ;
int ReceiveLoop ;
radio.stopListening();
bool isSend = false ;
for (SendLoop = 0 ; SendLoop <= maxSendLoop; SendLoop++) {
isSend = radio.write( outBuffer, strlen(outBuffer));
delay(35);
if (isSend == true ) {
Serial.print("sendloop : ");
Serial.println(SendLoop);
Serial.println("Send successful !");
radio.startListening();
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout ) {
delay(10);
if (millis() - started_waiting_at > 1500 )
timeout = true;
}
if( timeout ){
//If we waited too long the transmission failed
Serial.println("Failed, response timed out.\n\r");
return false;
}else {
//If we received the message in time, let's read it and print it
unsigned long got_time;
//radio.read( &got_time, sizeof(unsigned long) );
radio.read( inBuffer, strlen(outBuffer));
Serial.println(inBuffer);
Serial.print("Got response : ");
Serial.println((got_time-started_waiting_at)/ 1000 );
return true;
}
}
else {
Serial.println("Send FAILED !");
}
}
I had this reply ready to send and it just vanished --- xkkjdjxjjxs!!!!!
Let's see if I can recreate it ...
You have an awful lot of stuff IFs, WHILEs and more IFs all chucked in together which makes it very difficult to see what should be happening or what is actually happening. Try something like this
void loop() {
curMillis = millis();
sendMessage();
checkForReply();
}
void sendMessage() {
if (messageToSend == true) {
// code to send message
sentMessageMillis = curMillis;
messageToSend = false;
replyReceived = 'L'; // means listening
}
}
void checkForReply() {
if (replyReceived != 'L') {
return;
}
if (curMillis - sentMessageMillis >= timeoutMillis) {
replyReceived = 'T'; // means timeout
return;
}
// code to see if there is something available
// if there is
// get it
replyReceiver = 'R'; // means reply received
}
Hello Robin2 thanks for your fast replay. I have tried something like this .. .but i think that something is wrong ...
I can't get ( Timeout ) message is i turn off Receiver ap.. everytime i have curMillis - sentMessageMillis = 0 ;(
Below my code Thanks for answer
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 150; // the debounce time; increase if the output flickers
unsigned long curMillis;
unsigned long sentMessageMillis;
unsigned long timeoutMillis = 1500 ;
char replyReceived ;
RF24 radio(9,10);
// Example below using pipe5 for writing
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0x7365727631LL };
void OnPulse()
{
if ((millis() - lastDebounceTime) > debounceDelay) {
lastDebounceTime = millis();
sendMessage();
checkForReply();
}
}
void setup()
{
// pinMode(ledpin, OUTPUT);
attachInterrupt(1, OnPulse, CHANGE);
radio.begin();
radio.enableDynamicPayloads();
radio.setAutoAck(1);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setChannel(70);
radio.setRetries(15,15);
radio.setCRCLength(RF24_CRC_8);
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
}
void loop()
{
}
void sendMessage() {
radio.powerUp();
uint16_t nodeID = pipes[0] & 0xff;
char outBuffer[10]="Wyslano!";
radio.stopListening();
curMillis = millis();
bool messageToSend = radio.write( outBuffer, strlen(outBuffer));
if (messageToSend == true ) {
sentMessageMillis = curMillis;
messageToSend = false;
replyReceived = 'L'; // means listening
delay(15);
}
}
void checkForReply() {
char inBuffer[10];
if (replyReceived != 'L') {
return;
}
curMillis = millis();
Serial.println(curMillis - sentMessageMillis );
if (curMillis - sentMessageMillis >= timeoutMillis) {
replyReceived = 'T'; // means timeout
Serial.print("timeout");
return;
}
// code to see if there is something available
radio.startListening();
radio.read( inBuffer, strlen(inBuffer));
replyReceived = 'R'; // means reply received
radio.stopListening();
delay(20);
}
You can't call sendMessage() from an Interrupt Service Routine. ISRs muct be really really short. In your case it could probably set a variable called (say) readyToSend to true and then loop() would call sendMessage() which would only do anything if readyToSend == true.
Thanks for tip ;] i would like to use ISR to count pulses from kWh meter and sleeep for next interrupt. I would like to wake up radio for example only once per 10 pulses.
i would like to use ISR to count pulses from kWh meter and sleeep for next interrupt. I would like to wake up radio for example only once per 10 pulses.
In that case the ISR just adds 1 to a variable each time and sendMessage() (called from loop) only works when the count is 10 (or more) and when it sees a count of 10 it sets the counter back to 0.
I presume the kWh pulses don't happen all that fast.
Dear Collegues please help me to find out what is wrong with my code with sleep mode i Would like to enter into sleep mode after sending message but it works only for 4-6 pulses after that program suspends
#include <avr/sleep.h>
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
const long scaleConst = 1156.300 * 1000 ; // internalRef * 1023 * 1000;
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 90; // the debounce time; increase if the output flickers
int rpk = 1;
int nodeID = 1; // Pierwsze urz?dzenie ;)
int msg[1] = {1};
int rec[1] = {5};
RF24 radio(9,10);
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0x7365727631LL };
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
void setup()
{
Serial.begin(9600);
radio.begin();
radio.enableDynamicPayloads();
radio.setAutoAck(1);
radio.enableAckPayload();
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setChannel(70);
radio.setRetries(15,15);
radio.setCRCLength(RF24_CRC_8);
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
/* Setup the interrupt pin */
attachInterrupt(1, OnPulse, FALLING);
cbi( SMCR,SE ); // sleep enable, power down mode
cbi( SMCR,SM0 ); // power down mode
sbi( SMCR,SM1 ); // power down mode
cbi( SMCR,SM2 ); // power down mode
}
void loop()
{
//-------------------------------------------------------------
// 1) Enter sleep mode
//-------------------------------------------------------------
cbi(ADCSRA,ADEN); // switch Analog to Digital converter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
// The arduino is now sleeping...
//-------------------------------------------------------------
// 2) Program will resume from here on interrupt
//-------------------------------------------------------------
sleep_disable();
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
delay(10);
}
void OnPulse()
{
Serial.println("Pulse");
delay(200);
rpk++;
sendOverRadio();
}
bool sendOverRadio() {
char outBuffer[32]="";
radio.powerUp();
if (rpk >= 1000)
rpk=1;
delay(20);
sprintf(outBuffer,"% 2X",nodeID);
strcat(outBuffer,",");
char char_rpkLast[5];
String string_rpkLast;
string_rpkLast=String(rpk);
string_rpkLast.toCharArray(char_rpkLast,5);
strcat(outBuffer,char_rpkLast);
strcat(outBuffer,",");
int vcc = readVccMv();
char char_vcc[4];
sprintf(char_vcc,"%d",vcc);
strcat(outBuffer,char_vcc);
radio.stopListening();
delay(10);
radio.write( outBuffer, strlen(outBuffer));
// delay(20);
outBuffer[strlen(outBuffer)]=0;
while(! radio.isAckPayloadAvailable())
{
radio.read(rec,sizeof(rec));
if (rec[0] != 0) {
Serial.print("ACK Payload : ");
Serial.println(rec[0]);
Serial.println(rec[1]);
rec[0]=0;
rec[1]=0;
return true ;
}
else {
// rpk++;
Serial.println("No Ack in the AIR :(");
return false;
}
}
radio.powerDown();
}
int readVccMv() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
result = scaleConst / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return int(result);
}
The first two things that the interrupt service routine does are things that do not belong in interrupt service routines. The delay() function is waiting for the clock to tick a whole bunch of times. Notice the deafening silence, because the clock doesn't tick while your interrupt service routine is running.
There is REALLY nothing that your ISR needs to do. Every bit of the code in the ISR belongs in loop().