meet 2 Posted March 14, 2014 Share Posted March 14, 2014 Thanks for all your explanations. No, my code doesn't work, that's why I'm asking here any help Quote Link to post Share on other sites
spirilis 1,265 Posted March 14, 2014 Author Share Posted March 14, 2014 Thanks for all your explanations. No, my code doesn't work, that's why I'm asking here any help Ok, definitely get your PIR module working correctly & blinking an LED locally on the board before trying to diagnose the radio. Quote Link to post Share on other sites
meet 2 Posted March 14, 2014 Share Posted March 14, 2014 That's strange, I tried the code below and it doesn't work //PIR input on port P1_1 volatile int state = LOW; void setup() { pinMode(P1_1, INPUT); pinMode(RED_LED, OUTPUT); attachInterrupt(P1_1, A, RISING); } void loop() { digitalWrite(RED_LED, state); } void A(){ state = !state; } I checked the output pin of PIR and see that it give 3.4V when motion detected, so PIR is working. But I can't get P1_1 read this voltage and fire its flag to blink the red led on launchpad. Quote Link to post Share on other sites
spirilis 1,265 Posted March 14, 2014 Author Share Posted March 14, 2014 That's strange, I tried the code below and it doesn't work //PIR input on port P1_1 volatile int state = LOW; void setup() { pinMode(P1_1, INPUT); pinMode(RED_LED, OUTPUT); attachInterrupt(P1_1, A, RISING); } void loop() { digitalWrite(RED_LED, state); } void A(){ state = !state; } I checked the output pin of PIR and see that it give 3.4V when motion detected, so PIR is working. But I can't get P1_1 read this voltage and fire its flag to blink the red led on launchpad. Gotcha; Can you post a new thread about this in the Energia subforum? Just don't want this issue cluttering up the nRF24L01+ thread too much Thanks Quote Link to post Share on other sites
meet 2 Posted March 14, 2014 Share Posted March 14, 2014 Ohh sorry for that, sure. I'm going to solve this problem and come back if I can't settle the radio things Quote Link to post Share on other sites
meet 2 Posted March 15, 2014 Share Posted March 15, 2014 I fixed it, now it works but I can't run radio.begin inside the interrupt vector. It's working when it's defined on setup(), but as you said it means that radio is not sleeping. I can get the radio connection with code below, my PIR sensor trigger P1_4 and this cause interrupt fires, inside the interrupt vector I use the radio.print to send data to always wakened receiver. receiver read this data and blink a led. It works. // TX part #include <Enrf24.h> #include <nRF24L01.h> #include <string.h> #include <SPI.h> Enrf24 radio(P2_0, P2_1, P2_2); // P2.0=CE, P2.1=CSN, P2.2=IRQ const uint8_t txaddr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x01 }; const char *str_on = "ON_A"; void setup() { SPI.begin(); SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(1); // MSB-first P1DIR &= ~BIT4; P1REN |= BIT4 ; P1OUT &= ~BIT4; P1IE |= BIT4; P1IES &= ~BIT4; P1IFG &= ~BIT4 ; radio.begin(); // Defaults 1Mbps, channel 0, max TX power radio.setTXaddress((void*)txaddr); _BIS_SR(GIE + LPM4_bits); } void loop() { LPM4; } #pragma vector = PORT1_VECTOR __interrupt void A(void){ P1IFG &= ~BIT4; // radio.begin doesn't work here. radio.print(str_on); radio.flush(); // Force transmit (don't wait for any more data) delay(1000); } Do you have an idea how to awaken the radio inside the interrrupt service routine and make it sleep till a new interrup comes ? Thanks in advance spirilis. Quote Link to post Share on other sites
spirilis 1,265 Posted March 15, 2014 Author Share Posted March 15, 2014 You don't want to run begin() inside the interrupt routine, just inside setup(). Set another attachInterrupt for the radio's IRQ line and do an LPM4_exit inside that to fully wake up the chip. Then in your loop() process the radio message. Sent from my Galaxy Note II with Tapatalk 4 Quote Link to post Share on other sites
meet 2 Posted March 15, 2014 Share Posted March 15, 2014 Actually this loop things in energia confuse me, I can't use it efficiently. Another thing, it seems like TX radio sends continuosly data when triggered inside the interrupt vector, how can I make it stop ? #pragma vector = PORT1_VECTOR__interrupt void A(void){P1IFG &= ~BIT4;radio.print(str_on);radio.flush(); // Force transmit (don't wait for any more data)delay(1000); // sends data continuously, I want to stop it. Quote Link to post Share on other sites
spirilis 1,265 Posted March 15, 2014 Author Share Posted March 15, 2014 I can't say I have ever tried using any radio functions inside an ISR, because as a matter of design principle it's a terrible idea. ISRs are meant for flagging that some event has occurred so your main loop knows that it needs to process the results, or to do very light tasks like flipping an LED or whatnot. So I can't be of much help here. Sent from my Galaxy Note II with Tapatalk 4 Quote Link to post Share on other sites
meet 2 Posted March 15, 2014 Share Posted March 15, 2014 You don't want to run begin() inside the interrupt routine, just inside setup(). Set another attachInterrupt for the radio's IRQ line and do an LPM4_exit inside that to fully wake up the chip. Then in your loop() process the radio message. Sent from my Galaxy Note II with Tapatalk 4 I would do if I know how to do, but clearly I don't know how. Maybe it's a simple thing for you but I don't have enough information about it and that's why I'm asking here, to improve my knowledge. Maybe you can help more clear to me. Thanks a lot. Quote Link to post Share on other sites
spirilis 1,265 Posted March 15, 2014 Author Share Posted March 15, 2014 I would do if I know how to do, but clearly I don't know how. Maybe it's a simple thing for you but I don't have enough information about it and that's why I'm asking here, to improve my knowledge. Maybe you can help more clear to me. Thanks a lot. Ah okay, looks like you were a bit confused on what loop() et al is... Anyway, first off, Energia in its present form doesn't really "cater" to the use of LPM properly, imo. That may change in the future but I get the impression that using the LPMx commands as they are seems sufficient for most people, even though the millis() and micros() counters don't get correctly updated during that sleep mode. Take a look at the Getting Started tutorial so you know what setup() and loop() are there for- http://energia.nu/Tutorial_Sketch.html The problem with running lots of code inside an interrupt routine is that your code may affect peripherals that were in the midst of being modified by your loop() function... e.g. if you had a more complex app that updated an SPI LCD display, having nRF24L01+ radio commands inside an ISR could totally bomb if the ISR began and tried doing SPI communication with the radio while your main loop() code was in the middle of doing SPI I/O with an LCD display. That doesn't seem to be the case here, as your app is quite simple, but it's a very important thing to keep in mind when designing your sketches. Interrupts literally pull the CPU out of whatever it was working on, and branches it off to execute your interrupt routine code, with no regards to properly "cleaning up" the state of the system. So in general, a flag ISR should do something simple like update a "flag variable", and your main loop() should be where all the action is. Let me try rewriting your sketch to illustrate what I'm talking about: // TX part #include <Enrf24.h> #include <nRF24L01.h> #include <string.h> #include <SPI.h> Enrf24 radio(P2_0, P2_1, P2_2); // P2.0=CE, P2.1=CSN, P2.2=IRQ const uint8_t txaddr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x01 }; const char *str_on = "ON_A"; void setup() { SPI.begin(); SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(1); // MSB-first P1DIR &= ~BIT4; P1REN |= BIT4 ; P1OUT &= ~BIT4; P1IE |= BIT4; P1IES &= ~BIT4; P1IFG &= ~BIT4 ; radio.begin(); // Defaults 1Mbps, channel 0, max TX power radio.setTXaddress((void*)txaddr); } volatile boolean pir_flag = FALSE; // Flag variable void loop() { if (pir_flag == TRUE) { // PIR event detected; send radio message! radio.print(str_on); radio.flush(); // force transmission pir_flag = FALSE; } if (pir_flag == FALSE) { // probably not necessary but can't hurt // to put this conditional in there LPM4; } } #pragma vector = PORT1_VECTOR __interrupt void A(void){ P1IFG &= ~BIT4; // Signal to the main loop() that a PIR event has occurred. pir_flag = TRUE; // Exit LPM. LPM4_exit; } It's important to use the "volatile" keyword for the flag variable because that instructs the compiler to always pull its value from RAM; never try to rely on "saving" or "caching" a copy of it in registers and referencing that when the variable is read. Energia only runs setup() once, but it keeps re-running loop() forever. In this example, when no PIR event has been detected, the loop() function pauses in LPM4. When the ISR runs, LPM4 gets cancelled and when the ISR exits, the code after LPM4 in the loop() function is run; which is nothing, and so loop() just exits. But then Energia's core code re-runs loop(), where it will check that pir_flag variable and act on it if it's TRUE, or skip it and go back into LPM4 if it's FALSE. In this case your ISR is incredibly simple; it clears the P1IFG bit, sets a flag variable, and exits LPM4. In reality the flag might not actually be necessary since there is only 1 event that is capable of cancelling LPM. Also note I haven't done anything with the nRF24's IRQ. This is because this code is for the transmitter only; after radio.flush() completes, there is no reason to watch the radio's IRQ line. Your RX code will look different here; you'll need an ISR for the radio that sets a flag variable and some code in loop() to handle incoming radio data. meet 1 Quote Link to post Share on other sites
meet 2 Posted March 18, 2014 Share Posted March 18, 2014 I was thinking that you didn't write a response of my last post, I just find it out now. That codes make it all clear now, it's so explicit and very simple but incisive. Thanks for your guide, I'm going to apply this method to my nrf sensor nodes and hope it will work About the IRQ, is that something I need to use when I received data and want to close the connection with the transceiver pair? Because I observe that when TX sends data to RX, it latched connected each other(I prove that with powering rf on/off) and I don't know how to disconnect them. My code for RX is below; #include <Enrf24.h> #include <nRF24L01.h> #include <string.h> #include <SPI.h> Enrf24 radio(P2_0, P2_1, P2_2); // P2.0=CE, P2.1=CSN, P2.2=IRQ const uint8_t rxaddr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x01 }; const char *str_ona = "ON_A"; const char *str_onb = "ON_B"; const char *str_onc = "ON_C"; void setup() { SPI.begin(); SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(1); // MSB-first radio.begin(); // Defaults 1Mbps, channel 0, max TX power radio.setRXaddress((void*)rxaddr); pinMode(P2_3, OUTPUT); digitalWrite(P2_3, LOW); pinMode(P1_0, OUTPUT); digitalWrite(P1_0, LOW); pinMode(P2_4, OUTPUT); digitalWrite(P2_4, LOW); radio.enableRX(); // Start listening } void loop() { char inbuf[33]; while (!radio.available(true)) ; if (radio.read(inbuf)) { if (!strcmp(inbuf, str_ona)) digitalWrite(P2_3, HIGH); if (!strcmp(inbuf, str_onb)) digitalWrite(P1_0, HIGH); if (!strcmp(inbuf, str_onc)) digitalWrite(P2_4, HIGH); } } Thanks in advance, you improve my viewpoint. Quote Link to post Share on other sites
meet 2 Posted March 18, 2014 Share Posted March 18, 2014 By the way, LPM4_exit gives the error "was not declared on this scope". And I think it's a must to use it to start void loop() and check if flag is TRUE. edit: I used __bic_SR_register_on_exit(LPM4_bits) and it's solved. PIR node works perfectly! My question about the IRQ is still valid Quote Link to post Share on other sites
spirilis 1,265 Posted March 18, 2014 Author Share Posted March 18, 2014 By the way, LPM4_exit gives the error "was not declared on this scope". And I think it's a must to use it to start void loop() and check if flag is TRUE. edit: I used __bic_SR_register_on_exit(LPM4_bits) and it's solved. PIR node works perfectly! My question about the IRQ is still valid I'm a little puzzled by what you mean here. "Latched"? Does the TX side just continuously transmit? Or is the RX side reading the same thing over and over with it not flushing the results from the transceiver? I.e. does this issue stop if you only remove power from the TX side? Quote Link to post Share on other sites
meet 2 Posted March 18, 2014 Share Posted March 18, 2014 Yes, before it was like you described (stop if you only remove power from the TX side). But with the new code I tried it and it's fixed. Thanks again. I found deepsleep on your library, and used it before LPM4 line inside void loop(), and it works fine. I wonder what deepsleep realy do? I'm just trying to lower power consumption. And still wondering about IRQ you mentioned above. if (pir_flag == FALSE) { void deepsleep();// here it is LPM4; } } Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.