Wireless Bike Light using your code

I am using two RFM12bs to send code from the pushbutton to turn on or off my lights wirelessly on for my bike.  I have altered the send code that you use to send the energy code.  Everything works except that when I press for example, I press the button once, the code send -1 but then after a while even though nothing is pressed it resets itself to zero. 

 

The code works fine when I take out the watchdog but I was wondering if there is a way to keep the watchdog and save the variable somehow for lower power?

 

Below is code

#include <JeeLib.h>

#include <Arduino.h>

#define CLICK_DEBOUNCE_DELAY 20
#define CLICK_MULTICLICK_DELAY 250
#define CLICK_HELDDOWN_DELAY 5000
#define CLICK_PULLUP HIGH

// For now limit to tripleclicks
#define CLICK_MAX_BUTTON_PRESSES 3

// the decoded functions
#define CLICK_TRIPLECLICKED -3
#define CLICK_DOUBLECLICKED -2
#define CLICK_SINGLECLICKED -1
#define CLICK_SINGLECLICK 1
#define CLICK_DOUBLECLICK 2
#define CLICK_TRIPLECLICK 3
#define CLICK_SINGLEHOLD CLICK_MAX_BUTTON_PRESSES + 1
#define CLICK_DOUBLEHOLD CLICK_MAX_BUTTON_PRESSES + 2
#define CLICK_TRIPLEHOLD CLICK_MAX_BUTTON_PRESSES + 3
#define pin 7
              // Arduino pin connected to the button
    boolean reading;           // Current button state
    boolean active;            // Type of button - active LOW or HIGH
    boolean lastReading;       // previous button reading
    int buttonPressNr;         // Number of times button is pressed within CLICK_MULTICLICK_DELAY milliseconds
    boolean debouncedButton;   // the currently debounced button state
    long lastBounceTime;
     int click =0;

#define Button_Push 6
// the Button
//const int buttonPin1 = 7;
//ClickButton button1(buttonPin1, LOW,CLICK_PULLUP);

// Needs to store the previous returned button click code
int lastClickCode = 0;

int val = 0;
int old_val = 0;
int state = 0;

#define freq RF12_915MHZ                                                // Frequency of RF12B module can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have.
const int nodeID = 10;                                                  // emonTx RFM12B node ID
const int networkGroup = 210;                                           // emonTx RFM12B wireless network group - needs to be same as emonBase and emonGLCD

const int UNO = 1;                                                      // Set to 0 if your not using the UNO bootloader (i.e using Duemilanove) - All Atmega's shipped from OpenEnergyMonitor come with Arduino Uno bootloader
#include <avr/wdt.h>                                                    

#include <JeeLib.h>                                                     // Download JeeLib: http://github.com/jcw/jeelib
ISR(WDT_vect) { Sleepy::watchdogEvent(); }                              // Attached JeeLib sleep function to Atmega328 watchdog -enables MCU to be put into sleep mode inbetween readings to reduce power consumption

typedef struct { int buttonState;} PayloadTX;                           // create structure - a neat way of packaging data for RF comms
PayloadTX emontx;                                                     

                                                  // On-board emonTx LED

void setup()
{
  Serial.begin(9600);
  rf12_initialize(nodeID, freq, networkGroup);                          // initialize RFM12B
  rf12_sleep(RF12_WAKEUP);
  if (UNO) wdt_enable(WDTO_8S);                                         // Enable anti crash (restart) watchdog if UNO bootloader is selected. Watchdog does not work with duemilanove bootloader                                                             // Restarts emonTx if sketch hangs for more than 8s
  pinMode(pin,INPUT);
  pinMode(Button_Push,OUTPUT);
}

void loop () {
  digitalWrite(Button_Push,HIGH);

  reading = digitalRead(pin);
// if (!active) reading = !reading;   // Just to make the button logic in code active-high

  long now = (long)millis();         // prevents rollover issue by using signed arithmetic (I think)

  // If the switch changed, due to noise or pressing reset the debouncing timer
  if (reading != lastReading) lastBounceTime = now;

  // If no buttons were pressed within doubleClickDelay milliseconds, start a new buttonpress cycle
  if (now - lastBounceTime > CLICK_MULTICLICK_DELAY) buttonPressNr = 0;

  // Check if a debounced, changed state has occured
  if (now - lastBounceTime > CLICK_DEBOUNCE_DELAY && reading != debouncedButton)
  {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    debouncedButton = reading;

    // Check if the button is currently pressed down or not
    if (debouncedButton) click = ++buttonPressNr;
    else click = 0 - buttonPressNr;
  }

  // limit number of clicks / button presses
  if (buttonPressNr > CLICK_MAX_BUTTON_PRESSES) buttonPressNr = CLICK_MAX_BUTTON_PRESSES;

  // Check to see if a button is held down for a longer time
  if (debouncedButton && (now - lastBounceTime > CLICK_HELDDOWN_DELAY) && click < (CLICK_MAX_BUTTON_PRESSES+1))
  {
    // Set function according to a preceding doubleclick or not
    click += CLICK_MAX_BUTTON_PRESSES;
  }

  lastReading = reading;
  Serial.println(click);
  emontx.buttonState = click;
 
send_rf_data();                                                       // *SEND RF DATA* - see emontx_lib

}

 

Thanks,

Dawn

Robert Wall's picture

Re: Wireless Bike Light using your code

I can't see where you are resetting the watchdog timer. That's why it is timing out, and when that happens the program restarts from the top. You need "wdt_reset();" somewhere in your main loop.

Dawn's picture

Re: Wireless Bike Light using your code

That did the trick.

Thanks.

MartinR's picture

Re: Wireless Bike Light using your code

Isn't it also transmitting continuously? I can't see anything in loop() that causes any delay. If you're running on batteries, and to restrict radio channel use, you only need to transmit when the button is pressed.

Dawn's picture

Re: Wireless Bike Light using your code

I do want to do that along with other low power techniques but haven't written the code yet.  I keep running into unexpected issues with the signal.

cheers,

Dawn.

Robert Wall's picture

Re: Wireless Bike Light using your code

What kind of unexpected issues? They might be related to you transmitting continuously!

If I'm reading your code correctly, you're transmitting a number that relates to the history of button-presses every time your code loops, i.e. continuously, essentially limited only by the time taken to do the print statement and transmit the data.

I've no idea what you are actually trying to achieve, nor what you have at the receiving end, but it looks to me as if you are putting half your intelligence in the transmitter and half in the receiver. It would be easier if you concentrated all - or very nearly all - of the intelligence at one end or the other. Can I suggest that you rethink the overall strategy along these lines:

At the transmitter, debounce the switch and then send one code once (or maybe a small number of times, say 3 times at 100 ms intervals) meaning "the button has been pressed". Then at the receiver you implement the decoding to - I presume - toggle the lamp on and off for each button press.

Using that strategy, you could make it so that your pushbutton connected the power to the transmitter, which then transmitted the code more-or-less immediately. That would be the ultimate battery-saving technique - for the transmitter at any rate. The receiver clearly needs to be powered continuously in order to be able to receive the commands.

Dawn's picture

Re: Wireless Bike Light using your code

Is this what you mean?

Code from emontx lib.

void send_rf_data()
{
  rf12_sleep(RF12_WAKEUP);
  // if ready to send + exit loop if it gets stuck as it seems too
  int i = 0; while (!rf12_canSend() && i<10) {rf12_recvDone(); i++;}
  rf12_sendStart(0, &emontx, sizeof emontx);
  // set the sync mode to 2 if the fuses are still the Arduino default
  // mode 3 (full powerdown) can only be used with 258 CK startup fuses
  rf12_sendWait(2);
  rf12_sleep(RF12_SLEEP);
}

void emontx_sleep(int seconds) {
  if (emontx.battery > 3300) {
    for (int i=0; i<seconds; i++) {
      delay(1000);
      if (UNO) wdt_reset();
    }
  } else Sleepy::loseSomeTime(seconds*1000);
}

Robert Wall's picture

Re: Wireless Bike Light using your code

Dawn, I'm struggling to see the overall picture. I'm seeing some of the detail but I'm missing a lot - like what's happening at the receiving end. I'm worried that you're bogged down in detail when the detail isn't the problem. Can you tell me in words what you are trying to achieve and broadly how you are going about it?

(I'm looking for:
When I press the button on the transmitter once, it turns the light on.
When I press it twice in quick succession, it turns the light off.
In between, the light stays in the last state, either on or off.
In the receiver, the light is connected to a DIO pin via a driver transistor.

alternatively

When I press the button on the transmitter once, it sends a code every 10 s to turn the light on.
When I press it twice in quick succession, it sends a code to turn the light off.
If the transmitter goes out of range, the light turns off automatically after 25 s.

or something like that).

The emontx library that you quoted: the first function sends the data, the second sleeps the transmitter for a number of seconds, as a battery-saving measure. The first you will need, I don't think the second is going to be much use to you, but at this stage I can't tell for sure.

Dawn's picture

Re: Wireless Bike Light using your code

Robert,

Thank you for your reply.  Sorry, it took so long to get back to you.  I was having a hardware issue that took sometime to get sorted out.  I put up a very rough draft of project here, http://cycedtobike.com/project.html

The main problem is that after 2-5 minutes it stops working and then it has to be reset.  I tried a few different things with the code and it did not help.  I am thinking that the issue is because the watchdog probably needs to be used to prevent crashing, although when I put it in the code, it did not seem to help.

Does that seem right? or is there another issue going on?

 

Thanks,

 

Dawn.

MartinR's picture

Re: Wireless Bike Light using your code

I had a quick look at your circuit diagrams and I noticed that you have no series resistors for your optocoupler diodes. This will cause very large currents to flow which will at the very least flatten your battery quickly and may damage the ATmega chip.

You shouldn't need a watchdog if your code is working correctly. It's only intended as failsafe for when things go haywire.

Dawn's picture

Re: Wireless Bike Light using your code

I did add latter while trying to trouble shoot a 1k resistor to the optocoupler but I still keep running into the same problem.

Robert Wall's picture

Re: Wireless Bike Light using your code

The hardware problem:

I have not checked up on the opto-isolator that you're using, but having no current limiting resistor is, as Martin says, definitely wrong; but equally a 1 kOhm resistor sounds far too high. The LED in the opto is likely to require about the same current as any other LED, so I would expect a series resistor of around 100 R. You need enough current for the opto-isolator to work, but not so much that it blows up the Arduino.

Also as Martin says, the watchdog should reset the Arduino if the software locks up for an unknown and unforeseen reason. Ideally, it should never have a need to work.

The software problems:

It's a long shot, but use the very latest JeeLib release for the RFM12B drivers. An issue was discovered with the EmonGLCD software, and fixed within the last few days. It seems unlikely that you have the same conditions, but it's worth using the latest version nonetheless.

As for any other problems in there: sorry, my crystal ball has clouded over. Tell me in words what you are trying to achieve with the button(s), and I'll try to help you. You really can't expect me to spot a basic flaw in your logic until I know what you are trying to do. If you need to keep your specification secret, that's fine, send it to me in a PM.

Dawn's picture

Re: Wireless Bike Light using your code

Robert,

Trying the new release for the RFM12B driver is a really good idea.   Yes, I think you are right, the resistor.

Also, I posted a quick demo video and code here, http://cycedtobike.com/project.html.  The video and code is at the bottom of the page.  Is this the specifications you are talking about?

 

Thanks,

 

Dawn.

 

 

Robert Wall's picture

Re: Wireless Bike Light using your code

Sorry, that video won't download for me. All I want is some words - in the form that I posted on Thu, 07/02/2013 - 01:04. Now I've got the circuit diagrams of your transmitter - but it still doesn't show the pushbutton(s) - and the receiver, I've got a better idea of your hardware.

One point regarding that: you seem to be switching the a.c. supply to the electro-luminescent panels, but you're not switching the d.c. supply to the inverter. This means that the inverter will be running all the time and will drain your batteries. That might be a problem you want to address.

Dawn's picture

Re: Wireless Bike Light using your code

What it does is

when I push the button once, the device transmits  -1, and the el panel flashes on the right side and the left side is off

when I push the button twice,the device transmits  -2 and one the el panel flashes on the left side and the right side is off

when I delay click,the device transmits  0 and both el panels are flashing.

I reloaded the jeelabs library and it seems to be working better but it does need testing to be sure.

 

I know that my code need a lot of cleaning up, but added a zip file is that helps.

 

Thanks,

Dawn.

Robert Wall's picture

Re: Wireless Bike Light using your code

That's what I needed! OK, I'll take a look at the code later today or tomorrow and try to see what's wrong.

Robert Wall's picture

Re: Wireless Bike Light using your code

I see a gap in your specification: What turns the indications off?

And what is a "delay click"? Is it hold the button down for a long time?

Dawn's picture

Re: Wireless Bike Light using your code

I turn the indicator off by switching off the power with switched on my battery pack.

And yes, the delay click is holding it for a second or longer.

Robert Wall's picture

Re: Wireless Bike Light using your code

These two sketches seem to work for me using "standard shop" emonTx as the transmitter and nanodeRF as the receiver.

I think the main problem was there were no delays in the main loop so it was catching its own tail. RF is now only sent every 400 ms.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.