/projects/codam-light/img2.png

Codam light

Published @ 08-07-2024

#low-power #barebones #rf24 #ledstrip

— “Red means DON’T ENTER!”

The project was originally Daoyi’s idea, my contributions are the electronics and some parts of the code.
the plan was to build a light for each of the auditorium doors that change colours to show what is happening inside, plus a smaller light inside auditorium to act as visual feedback. The lights are controlled with a single remote over radio communication.

Electronics

Remote

The remote has 4 buttons each corresponding to a different light color, each button is hooked up to a interrupt pin. It is built around a barebones ATmega328p chip running on its internal oscillator at 8Mhz. The main design constraint for the remote was making it energy efficient, so it could run off a coin cell battery.

Internal oscillator

We’re running it off of its internal oscillator to reduce part count and save some power. To get to set this up we had to flash a different bootloader, mainly because it seemed easier than setting the fuses by hand.

We used 2 Arduino Uno’s one as a programmer loaded with this sketch, and another as the target device, aka the chip that will be in the remote.
This post explains how to set it up.

Reducing current consumption

This site has a lot of information on the topic.

  • Processor always sleeping only waking up on interrupts.
  • Turn off the Watchdog timer (WDT).
  • Turn off the brown out detector (BOD).
  • Setting unused pins as output.
  • Because of the coincell the supply voltage is around 3V which would probably reduce the clock frequency

Applying these tricks we got the consumption down to around 2.6uA while sleeping, now I’m not sure how accurate this number is since I’ve only measured it with one multimeter. But say the battery has 210mAh and we’re drawing 2.6uA that would put us at around 9 years, so pretty good :)

[TBA PIC OF REMOTE]

Light

Light strips

The lights are 24V-RBGW led strips, they are driven by a 4 channel mosfet board, which is controlled by an Arduino Pro Micro. All being powered by a 24V LED powersupply, which needed some tricks to get working.

Controller board

The 24V supply feeds into a buck-converter generating the board’s 5V rail.

It features a RF24 radio module, with an 3v3 LDO adapter board to so it can run off of the 5V rail provided by the buck-converter.

We went with the RF24 after some experimentation with other radio modules, mainly because it has some ✨ TCP acknowledgement ✨ thing going on, improving the reliability of the system. It uses SPI allowing you to configure some more settings compared to a simple 4 button garage door type radio.

Inrush current

The 24V LED supply could not handle the (pretty small) inrush-current the buck-converter had, so after experimentation I added a inductor in series between the buck-converter and the 24V supply, which fixed the issue.

I found this fix when swapping out different 24V power supplies and noticing that with a longer wire between the power supply and the buck-converter it would work, but not if I used a smaller wire.








Insides of small light (the tape was temporary)

img

Back assembly of a large light

img

Software

You can checkout the software repo over here.

Payload

The thing both the Light and Remote have in common is the ✨ Payload ✨, this payload has a few things to it.
It is essentially a 1 byte word being used as bit-fields, where the 4 MSB each correspond to one of the four buttons on the remote.
The 4 LSB correspond to the address of each light, when the remote sends a payload these fields are cleared. Say light LD1 receives the payload: It will set its own bit-field and foward it to the other lights that don’t have their field set.
This is super dirty way to make a “mesh” network, it also adds a bit more redundancy incase a light is out of range of the remote, but still in reach of another light.

Remote

We used 2 wrapper libraries to handle interfacing with the ATmega’s registers.

The code for the remote can be boiled down to the following steps.

  • Setup the RF24 over SPI.
  • Setup pinChangeInterrupt() on the button pins.
  • Call LowPower.powerDown() to sleep forever until we hit an interrupt.
  • When an interrupt fires it will wake up the CPU and will store the pin which triggered the interrupt.
  • When the CPU is running it will call radioSend() with the saved button, which will generate the payload and send it.
  • After that it will hit another LowPower.powerDown() and the whole cycle repeats.

Light

This part is very simple. The light will poll the radio for the incomming payload, when it receives anything it will foward it to the lights that have not received this payload yet. After that it will set the 4 PWM channels to the corresponding color.







Final results



img

Resources

Nick Gammon has a great forum filled with tons of knowledge which helped a lot.

© 2024 Joppe Boeve. All rights reserved.