Looking for feedback on my water tank lights automation

Hi all,

I've put together a circuit that can control LED component (UPD: it is not an individual LED, see the pic below. sorry for not mentioning this early) I scraped from another lamp. Now it does everything I need it to do: schedule for time on/off, remote control on/off, control of brightness. For the projects I used components available in Elegoo Starter Kit, so had to improvise in some parts.

My end goal is to 3D print a cover for the tank that will hide the board and all components in it. For that I want to solder everything on the prototype extension board. But before moving on to soldering, I wanted to ask for your feedback on my circuit as I this is my first project.


I'd appreciate any kind of suggestions/ feedback, but here are a couple of questions I wanted to ask:

  • I don't have a component to programmatically control resistance (digipot?), so had to put together an array of transistor/resistor pairs. With that I can control the brightness of the external LED. Is this an OK approach or shall I order a specialised component for this? I also noticed that I loose some quite some power with all "gates open". Do NPN transistors create significant resistance when "open"? Didn't figure out how to use multimeter to measure it.
  • What's the best way to plan out placement of the components before soldering? I've put together schematics in Eagle, what would be the next step? Design an empty stripboard and place components in Eagle? Are there any sample projects for this process? Couldn't find any....

Thanks!

Isn't PWM a better solution to control the brightness? Only one transistor or better one MOSFET to switch on/off and PWM.

Go in eagle to BRD. Place the components on it. Make the traces. Make gerbers and send they to a PCB house like JLCPCB. For each step there are many tutorials and YouTube pictures.

1 Like

YIKES !

It looks like you'll short +5V to GND through the relay (NC & Common).

Also it only looks like you've connected 1 side of your relay coil.

Pat.

It's an inventive circuit, but it may not work the way you expect. The emitter bias voltage will differ according to which transistors are turned on. That will prevent uniform switching of the transistors. If you must use discrete transistors, use them in common emitter configuration with all emitters grounded, to switch parallel, not series resistors.

The much easier way is to use PWM.

1 Like

Great schematic, thanks!

1 Like


3D printed mounts on 1/4" Lexan. Mega has terminal shield and PDB - Power Distribution Board on top


Detail of CPU stack


Adding wiring.

PWM would be the preferred way to go. Arduinos know how to do it and it would greatly simplify your logic and design.

thank you everyone for the answers! I've tried PWM, but it doesn't seem to be working with the LED panel I have. I guess they have some controls preventing it there - can't read the components. This is how it looks like:

thanks aarg! I'm sure it's a stupid question, but do you mean something like this?

Sort of. You show the basic idea, but the way it's placed is completely wrong in many ways. It doesn't really matter at this point because you should be using PWM. Else, you need several more months or years of study of electronics before you can design this.

Edit - oh you have a panel with a driver circuit on it. Have you tested it with a variable voltage or variable current supply to see if that will even work?

It's mildly annoying that you didn't relate this before, like in the first post...

Also what is the purpose of the relay in your circuit? It switches 5V between an I/O pin and ground. So it shorts out the power supply. When D8 isn't selected, it is open circuit so it is either a "floating input" or an output that can be damaged if it ever goes LOW while the relay connects 5V to it.

If you want corrections on this very sketchy design, you have to explain how you think it should work, i.e., what you expect each component to do and why.

I just noticed that some of these points were raised in reply #3, yet there seems to be no acknowledgement or action.

Look at your relay again...

moot if you go to PWM, as recommended.

OP claims PWM doesn't work. But as with the rest of the posts, shy on details...

I'm not sure how the OP intends to use the relay. The coil appears to be connected to the transistors and the NC contacts will short power to ground.

I'll check here for significant updates. If there are few or none, I'm out...

Is it me, or do the four transistors need a base resistor? And they're NPN with the emitter connected to the wrong rail? No kickback diode on the relay coil?

It's not you. A (probably last) comment. This shouldn't go to PCB before a working prototype is proven.

sorry for the lack of details and not giving proper responses to your suggestions. It's not because I ignore them or lazy to provide details. It's the first circuit I'm building in my life, the first time I'm drawing schematics and the first time I'm using Eagle - so simply don't have enough experience. Again, sorry for that - I appreciate your time and trying to help! And it's my bad I didn't post details about LED circuit.

How I expect everything to work:

  • Arduino is powered by the external 9V wall socket
  • External LED panel is hooked up the Vin pin to have enough power
  • Relay is controlled by arduino digital pin to break negative - switch the led on/off
  • the array of transistors is my attempt to programmatically control resistance on LED panel loop and by that control brightness of the light.
  • The first transistor is used to skip or not the rest of transistors+resistors as even "open" transistors significantly reduce the brightness.
  • At some point the LEDs were flickering and I thought it's because of the unstable power supply, so I added a couple of capacitors in front of the LED circuit. Not sure if it was bad contacts and not sure if those capacitors are needed, but he flickering is gone now.

The prototype on my first schema works. The brightness, as aarg rightly said, is not linear, but still works. It's possible my schematics are not correct - again, that's my first time doing it and I struggle a lot :slight_smile: Let me try to revisit it and correct.

PWM: the way I tried it is hooked up analog output to the transistor to base and LED panel to emitter. I did analog write 0-255 on base pin and the LED panel only lights up on 255 value. I guess this is completely wrong?

UPDATE: I will also attach my code, maybe it will do better job at explaining the logic than I do:

#include <Wire.h>
#include <DS3231.h>
#include <IRremote.hpp>

#define IR_RECEIVE_PIN 2
#define RELAY_PIN 8
#define RESISTOR1_PIN 3
#define RESISTOR2_PIN 4
#define RESISTOR3_PIN 5
#define RESISTOR4_PIN 6
#define RESISTOR5_PIN 7
#define DIMMER_LEVEL_MAX 5

DS3231 myRTC;
DateTime dt;
uint8_t dimmer_level;

// schedule to switch the light ON. Format HHMMSS
long switch_on[] = { 73000, 170000 };
// Schedule to switch the lights off. Format HHMMSS
long switch_off[] = { 113000, 230000 };

void setup() {
  Serial.begin(9600);
  Serial.println("IR Receiver Button Decode");
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
  pinMode(RELAY_PIN, OUTPUT);

  Serial.println("Initialize RTC module");
  Wire.begin();
  DateTime dt = RTClib::now();
  Serial.print("- DS3231 module init year: ");
  Serial.println(dt.year());

  if (dt.year() == 2000) {
    Serial.println("- Setting module's date time to compile date:");
    Serial.print("  ");
    Serial.print(__DATE__);
    Serial.print(" ");
    Serial.println(__TIME__);

    static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
    static char buff[4] = { '0', '0', '0', '0' };
    int y, m, d, hh, mm, ss;

    sscanf(__DATE__, "%s %hhu %d", buff, &d, &y);
    m = (strstr(month_names, buff) - month_names) / 3 + 1;
    sscanf(__TIME__, "%hhu:%hhu:%hhu", &hh, &mm, &ss);

    myRTC.setClockMode(false);  // set to 24h
    myRTC.setYear(y - 2000);
    myRTC.setMonth(m);
    myRTC.setDate(d);
    myRTC.setHour(hh);
    myRTC.setMinute(mm);
    myRTC.setSecond(ss);
  }

  set_dimmer();
}

int inarray(long val, long arr[]) {
  int i;
  for (i = 0; i < sizeof(arr); i++) {
    if (arr[i] == val)
      return 1;
  }
  return 0;
}

void translateIR() {
  switch (IrReceiver.decodedIRData.command) {
    case 0x45:
      Serial.println("ON");
      digitalWrite(RELAY_PIN, HIGH);
      break;
    case 0x46: Serial.println("TIMER"); break;
    case 0x47:
      Serial.println("OFF");
      digitalWrite(RELAY_PIN, LOW);
      break;
    case 0x44: Serial.println("1"); break;
    case 0x43: Serial.println("2"); break;
    case 0x7: Serial.println("3"); break;
    case 0x9: Serial.println("4"); break;
    case 0x16:
      Serial.println("5");
      break;
    case 0xD:
      Serial.println("6");
      break;
    case 0xC:
      Serial.println("7");
      break;
    case 0x5E:
      Serial.println("8");
      break;
    case 0x8:
      Serial.println("DOWN");
      dimmer_level = dimmer_level == DIMMER_LEVEL_MAX ? DIMMER_LEVEL_MAX : ++dimmer_level;
      Serial.print("Setting dimmer level to ");
      Serial.println(dimmer_level);
      set_dimmer();
      break;
    case 0x5A:
      Serial.println("UP");
      dimmer_level = dimmer_level == 0 ? 0 : --dimmer_level;
      Serial.print("Setting dimmer level to ");
      Serial.println(dimmer_level);
      set_dimmer();
      break;
    default: Serial.println(" other button   ");
  }

  delay(500);  // Do not get immediate repeat
}

void set_dimmer() {
  switch (dimmer_level) {
    case 0:
      set_dimmer_resistors(HIGH, LOW, LOW, LOW, LOW);
      break;
    case 1:
      set_dimmer_resistors(LOW, HIGH, HIGH, HIGH, HIGH);
      break;
    case 2:
      set_dimmer_resistors(LOW, LOW, HIGH, HIGH, HIGH);
      break;
    case 3:
      set_dimmer_resistors(LOW, LOW, LOW, HIGH, HIGH);
      break;
    case 4:
      set_dimmer_resistors(LOW, LOW, LOW, LOW, HIGH);
      break;
    case 5:
      set_dimmer_resistors(LOW, LOW, LOW, LOW, LOW);
      break;
    default: Serial.println("Error: unknown dimmer level");
  }
}

void set_dimmer_resistors(uint8_t res1, uint8_t res2, uint8_t res3, uint8_t res4, uint8_t res5) {
  digitalWrite(RESISTOR1_PIN, res1);
  digitalWrite(RESISTOR2_PIN, res2);
  digitalWrite(RESISTOR3_PIN, res3);
  digitalWrite(RESISTOR4_PIN, res4);
  digitalWrite(RESISTOR5_PIN, res5);
}

void loop() {
  if (IrReceiver.decode()) {
    translateIR();
    IrReceiver.resume();
  }

  DateTime dt = RTClib::now();

  long currenttime = (long)dt.hour() * 10000 + (long)dt.minute() * 100 + dt.second();

  if (inarray(currenttime, switch_on)) {
    digitalWrite(RELAY_PIN, HIGH);
  }

  if (inarray(currenttime, switch_off)) {
    digitalWrite(RELAY_PIN, LOW);
  }
}

thanks for the tip! I simply was not aware those might be needed and somehow the circuit worked without both :slight_smile: I think I found a nice article on this and will try to do my math on this. Quick stupid question: if the circuit works as it is, what symptoms of missing base resistor and kickback diode are? overheating of the transistor? or are those components for safety and abnormal operation?

What do you mean by "analog output"?
if you mean analog pins A0 -A5 those are Analog Inputs only.
Despite the poor name choice of "analogWrite" PWM is not analog and can only be performed on pins 3,5,6,9,10,11 on an Uno. The pins marked with a "~" are PWM capable

yes, that's exactly what I did. Switched digital pin 3 (connected to transistor base) to output and used analogWrite. emitter and collector hooked up to led's negative.