I have a bunch of "street lights" that are pretty nice and one of them broke.
They have a dedicated PCB that I can't source, so I thought I would use a Tiny to get it to work again.
It has a solar panel, an array of 42 LEDs on just one set of two wires, a Li-Ion 3.7V battery and a PIR motion sensor.
I thought of buying a 3.7V Li-Ion charging module and using an 8 pin ATTiny to drive the LEDs.
I have a few challenges, though.
I can probably do a voltage divider and use the Tiny ADC input to figure out when to turn the lights on or off (day/night detection). The tiny may not use too much energy, especially if I put it to sleep during the day and only wake it to check if it's night time, then keep it on until dawn or battery depletion.
So the inputs for the Tiny (ADC and PIR) should be pretty straightforward.
It has two modes, motion sensing on/off and 1/2 bright on/full on when motion detected.
The biggest issue is the LED array. I used a working light to measure voltages and I get 2.83V when fully lit and 2.28V when dim. That could be an indication that it uses PWM or some other method to drive the array.
Since it only has two leads, I will need a driver transistor to drive the LEDs and to dim it, I will try to use PWM rather than a resistor. I can try to measure the current on a working light to calculate a resistor so that applying 3.7 to 4.2V won't cook the LED array.
With that said, I could appreciate your thoughts on how to go about tackling this project or if you think that my approach is sound.
PWM switches between full-on and full-off rapidly so the LEDs appear dim to the eye. But while they are on they (and the transistor or MOSFET) will get excess current.
The best (and most energy efficient) solution is a switch-mode constant current source. Most "high power" LEDs use a constant current source. But it's not an easy thing to build.
And if you use resistors, each LED should have it's own resistor (if they don't already) because if the LEDs are in parallel you can't count on the current dividing evenly.
If they are in series (which is more common for this kind of application) you'd need a voltage-boosting circuit plus current control-limiting.
I doubt they are in series, as the 2.8V on the two wires indicates when they are lit.
They do light up evenly, so even if they are in parallel, it’s not noticeable.
As a first step, I have to try to measure the current when lit, then calculate a single resistor so that Incan apply the full 3.7V to the array.
The original circuit may have a switching power source because of the two mode of lighting (full and dim), but I have to try to simulate that somehow.
I don’t mean to antagonize anybody and I truly appreciate people replying, even if it’s to ask questions.
I apologize if I came across as a [insert adjective here], it looked like kolaha’s original post with the 1.2V garden light schematic rubbed me the wrong way. Kolaha, sorry, you were willing to help and I reacted poorly. I thought the ‘Access denied’ reply was directed at me, but I see that you updated it and it was referring to the URL.
With that said, I don’t think these are on high voltage.
3.7V is more than enough to drive LEDs in parallel.
True, from a 1.2V battery you can’t light up one and you need to upvolt.
I get like 2.8V when lit, so I think they are in parallel. That could mean 1A for the whole array.
Once I remove the original board, I will try to see if there is a resistor.
OK, just for the sake of closure, if anyone is interested, here is the resolution.
The street light had a dedicated IC, which not only controlled the lights, but also served as the amplifier for the PIR bare sensor, and also as battery charging management.
So I had to replace all functional components to make it work again.
I used a solar charging module for the 3.7V Li battery, but to keep it cheap, I went with a 5V one, so I had to use a buck converter between the solar panel and it. That’s because the solar panel puts out almost 7V in full sun.
Then I had to use a SR501 PIR sensor module that has a digital output and an ATTiny85 to control everything.
I used the original switch and the output portion of the original module, which includes a MOSFET driver and a 0.9ohm resistor for the bank of LEDs.
So right now it’s working great, the Tiny controls PWM output and the lights are dimmed until the PIR senses motion, when it goes to full on.
Total cost to repair was less than $5 and I can now control everything about the light.
If anyone would like detail, please ask.
Thanks for your interest, I will do my best to create a schematic and I will post the code. It’s rather simplistic, so I will try to describe my approach.
The solar panel puts out close to 7V, so I got a buck converter module that drops to 5V, because I got a battery management module that requires 5V input for the 3.7V Li battery in the light.
The battery powers the Tiny module that I built on a perforated project board. The tiny85 is an 8 pin DIP with 5 pins if you still keep the reset. I used one input for the switch that dictates the operating mode (off or dim when there is no motion), one for the PIR digital out, one analog input for a voltage divider connected to the 5V output from the buck converter (to determine when it’s dark). I used one for PWM out and the last one as serial out Tx, so that I can troubleshoot.
From the original board I cut out the LED bank driver and resistors. It uses a 2302 MOSFET, which was still working, so I didn’t want to replace it.
More to come, I will post the code, which is really simple, but maybe someone can chime in with ideas to improve it.
And I may have discovered that an LDO converter may be the culprit, because another one broke and that SMD component looks fried. I will replace it and see if that takes care of it, but I have my doubts, because I measured 4.5V on the output, so that may have cooked the 3.3V IC controller on the original board.
Here is the latest code, after a bunch of tweaking.
It may help someone working on a similarproject.
If not, the Tiny internal voltage measurement may be worth looking at, because it works great.
That took a lot of digging and trial/error, because the first read should be dropped.
Also, the PIR was being triggered by the lights turning off, so I had to add a delay to disable reading the PIR while its output was still high.
Please note that I am using Dr. Azzy's core: ATTinyCore
#include "tinysnore.h"
int pwmPin = 1; // PWM output to LEDs
int pirPin = 2; // PIR input
int swPin = 4; // switch Dim/PIR - PIR
int outPin = 0; // power out to PIR or Tx
int voltPin = A3; // i/o pin 4 solar voltage
int readVolt;
int readBat;
int dim = 32;
int onTime = 20000;
int pirOff = 5000;
unsigned long batInterval = 300000L; // 5 min
unsigned long snoreTime = 14400000L; // 4 hours
unsigned long refMillis;
unsigned long disMillis;
unsigned long batMillis;
unsigned long debugMillis;
boolean lightsOn = false;
boolean dimLights = false;
boolean pirDisable = false;
//boolean debug = false;
void setup() {
pinMode(pirPin, INPUT);
pinMode(swPin, INPUT);
analogWrite(pwmPin, dim);
delay(200);
analogWrite(pwmPin, 0);
delay(200);
analogWrite(pwmPin, dim);
delay(200);
analogWrite(pwmPin, 0);
delay(200);
analogWrite(pwmPin, dim);
delay(200);
analogWrite(pwmPin, 0);
/* if(debug){
Serial.begin(9600); // connect Rx from ftdi to pin 0 on Tiny
Serial.print("Vcc ");
Serial.println(readBat);
debugMillis = millis();
}*/
batMillis = millis();
}
void loop() {
if(millis() > (batMillis + batInterval)){
checkBat();
}
readVolt = analogRead(voltPin);
if(readVolt < 10){ // low solar -> night time, lights on
if(!pirDisable && digitalRead(pirPin) == HIGH){ // motin detected, full on for onTime millis
lightsOn = true;
refMillis = millis(); // start timing lights on
}
if(lightsOn && (millis() > (refMillis + onTime))){ // lights on time elapsed
lightsOn = false;
pirDisable = true;
disMillis = millis(); // start timing PIR disabled
}
if(pirDisable && (millis() > (disMillis + pirOff))){
pirDisable = false;
}
if(lightsOn){
analogWrite(pwmPin, 255);
}else{
if(dimLights){
analogWrite(pwmPin, dim);
}else{
analogWrite(pwmPin, 0);
}
}
/* if(debug && (millis() > (debugMillis + pirOff / 4))){
Serial.print("solar ");
Serial.print(readVolt);
Serial.print("\tdimLights ");
Serial.print(dimLights);
Serial.print("\tlightsOn ");
Serial.print(lightsOn);
Serial.print("\tpirDisable ");
Serial.println(pirDisable);
debugMillis = millis();
}*/
}else{ //it's daytime
lightsOn = false;
pirDisable = false;
analogWrite(pwmPin, 0);
}
}
void checkBat(){
readBat = readVcc();
/* if(debug){
Serial.print("Vcc ");
Serial.println(readBat);
}*/
if(readBat < 3000){ // bat < 3000 mV -> discharged, snore
analogWrite(pwmPin, 0);
snore(snoreTime);
}
if(readBat < 3400){ // save power when bat is lower
dimLights = false;
}else{
if(digitalRead(swPin) == LOW){
dimLights = true;
}else{
dimLights = false;
}
}
batMillis = millis(); // start timing check battery
}
long readVcc() {
// reads internal 1V1 reference against VCC
// https://github.com/cano64/ArduinoSystemStatus
ADMUX = _BV(MUX3) | _BV(MUX2); // For ATtiny85/45
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC));
uint8_t low = ADCL;
unsigned int val = (ADCH << 8) | low;
//discard previous result
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC));
low = ADCL;
val = (ADCH << 8) | low;
return ((long)1024 * 1100) / val;
}
And here is the diagram, if anyone needs it.
I still have to experiment without the buck converter, that is the reason for the question marks.
The solar panel output may not exceed 8V, which is the maximum the charging chip can take, so I will give it a try.