Circuit & Code Verification

Let me start off my saying that this is my first project, so bare with me.

I am looking for advice / verification on my code and circuit. Everything works, but I am not sure if I may be missing something such as a diode, capacitor, extra resistance, etc.

My project is essentially turning a mini-freezer into a fridge/freezer using a digital temperature sensor (I was going to use a straight thermocouple, but I didn't want to design the instrumentation circuit).

I have attached my circuit diagram (sorry if it's difficult to read, never made one before), as well as my code. Please let me know if there's something I'm missing or need to improve.

Couple notes on this diagram: the temp sensor is digital, I just used a placement block to simulate it. The Vout is actually the digital signal output. And the motor is an AC pump, again a placement.

#include <OneWire.h>
#include <LiquidCrystal.h> 

//pin declaration
int analogTempSet = A0; //temperature pot value
int DS18S20_Pin = 2; //DS18S20 Signal pin on D2
int relayPin = 3; //initiating the relay pin on D3

LiquidCrystal lcd(4, 5, 10, 11, 12, 13);

byte degree[8] = { //making the degree symbol
  0b00110,
  0b01001,
  0b01001,
  0b00110,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};

//variable declaration
float tempValue = 0; 
float setTemp = 0;
unsigned long currentSecs = 0;  //time since the relay was last powered
unsigned long previousSecs = 0;
int relayPowerInterval = 10; //interval that the pump should take before turning on again (in seconds)

OneWire ds(DS18S20_Pin); 

void setup() {
  pinMode(relayPin,OUTPUT);
  lcd.createChar(0, degree);
  lcd.begin(16,2);
 
  Serial.begin(9600);

  
}

void loop() {

  currentSecs = millis() / 1000; //the time the relay has been active in seconds

  //set temp reading (pot input)
  tempValue = analogRead(analogTempSet);  //read the current setting
  //tempSet = map(tempValue,0,1023,-220,50) / 10.0;  //map the pot to temp range
  setTemp = map(tempValue,0,1023,150,340)/10.0; //TEST LINE
  
  //curret temp reading (sensor return)
  float currentTemp = getTemp();

  if (currentTemp > setTemp  ) {
                                        //this is to prevent the pump from switching on and off too frequently
    if ((unsigned long)(currentSecs - previousSecs) >= relayPowerInterval){
             
          digitalWrite(relayPin, HIGH); //power the relay coil
          previousSecs = currentSecs;
        
    }
     
  }
  else{
    digitalWrite(relayPin, LOW);
  }

  lcd.setCursor(0,0);
  lcd.print("Set: ");
  lcd.print(setTemp, 1);
  lcd.write(byte(0));
  lcd.print("C");

  lcd.setCursor(0,1);
  lcd.print("Current: ");
  lcd.print(currentTemp, 1);
  lcd.write(byte(0));
  lcd.print("C");

  Serial.println(setTemp);
  Serial.println(currentTemp);
//  Serial.println((currentSecs-previousSecs));
  
  delay(1000);        // delay in between reads for stability
}


//returns the temperature from one DS18S20 in DEG Celsius
float getTemp(){
 byte data[12];
 byte addr[8];
 if ( !ds.search(addr)) {
 //no more sensors on chain, reset search
 ds.reset_search();
 return -1000;
 } 
 
 if ( OneWire::crc8( addr, 7) != addr[7]) {
 Serial.println("CRC is not valid!");
 return -1000;
 }
 
 if ( addr[0] != 0x10 && addr[0] != 0x28) {
 Serial.print("Device is not recognized");
 return -1000;
 }
 
 ds.reset();
 ds.select(addr);
 ds.write(0x44,1); // start conversion, with parasite power on at the end
 byte present = ds.reset();
 ds.select(addr);
 ds.write(0xBE); // Read Scratchpad

 for (int i = 0; i < 9; i++) { // we need 9 bytes
 data[i] = ds.read();
 }

 ds.reset_search();

 byte MSB = data[1];
 byte LSB = data[0];
 float tempRead = ((MSB << 8) | LSB); //using two's compliment
 float TemperatureSum = tempRead / 16;

 return TemperatureSum; 
}

Probably could use some capacitance to keep the noise off your analog value from the TMP36 and it’s resolution could be improved but that’s for later.

For now, what is current rating or coil resistance of the 5v relay you’re using? Also, a part number for Q1?

PS: karma given for a decent schematic and properly posting your code.

The coil current on that relay is 80.0mA, with a contact rating of 10A. I do notice that when the coil is activated the LCD dims a bit, I'm hoping a direct power supply providing 650mA instead of the USB's 500 will fix this.

And Q1, that transistor, is S8050.

Good job on the posting :slight_smile:

Regarding the output of the DS18S20, R5 (4.7Kohm) needs to be a pullup resistor to Vcc, not a series resistor.

The LED dimming could be your wiring or the 5k pot used for brightness, it’s too high of a value. It’s much better to use a PWM output into a PNP transistor to control the LED brightness if you need to dim the display backlight.

With an 80 ma relay, you want approximately 10% of that current in to the base of the S8050 to insure it saturates, that is to get its collector voltage as low as possible to keep the power dissipation as low as possible. In order to do that, R4 should be approximately 510 ohms*. You should eliminate R3 as it is unnecessary and just forms an undesirable voltage divider that lowers the base drive current.

  • is calculated from 5 volts less the base-emitter drop of .7 volts so 4.3 / .08 / 10 = 537.

cattledog:
Regarding the output of the DS18S20, R5 (4.7Kohm) needs to be a pullup resistor to Vcc, not a series resistor.

That was one thing I was confused about.. I sort of understand the pullup/pulldown concept, but I wasn't sure how to implement it. The notes on the DS18S20 didn't really break it down to well. I found the way I have it now worked, so I didn't really bother to figure it out anymore.

How would I implement it in this case? The spec sheet mentioned something about parasitic voltage to run it, but I still got confused and just left it.

WattsThat:
The LED dimming could be your wiring or the 5k pot used for brightness, it’s too high of a value. It’s much better to use a PWM output into a PNP transistor to control the LED brightness if you need to dim the display backlight.

With an 80 ma relay, you want approximately 10% of that current in to the base of the S8050 to insure it saturates, that is to get its collector voltage as low as possible to keep the power dissipation as low as possible. In order to do that, R4 should be approximately 510 ohms*. You should eliminate R3 as it is unnecessary and just forms an undesirable voltage divider that lowers the base drive current.

  • is calculated from 5 volts less the base-emitter drop of .7 volts so 4.3 / .08 / 10 = 537.

I'll look into setting up the PWM for the brightness. I've read about it and sort of wanted to avoid it (obviously easier is lazier), but it probably is the better route, and might fix that dimming like you said.

Interesting note on the npn.. I never really thought of calculating it, just went with a diagram I found online. And now that you mentioned it, I do realise that R3 has no reason to be there. Thanks for the input!

That was one thing I was confused about.. I sort of understand the pullup/pulldown concept, but I wasn't sure how to implement it. The notes on the DS18S20 didn't really break it down to well. I found the way I have it now worked, so I didn't really bother to figure it out anymore.

How would I implement it in this case? The spec sheet mentioned something about parasitic voltage to run it, but I still got confused and just left it.

The pullup resistor is necessary for parasitic power, but it also works as part of the bus management and communication protocol. It's possible that the internal pullup resistor of the Arduino will be sufficient, but I don't see either you or the library using INPUT_PULLUP as the pin mode.

I'm somewhat surprised that the sensor indeed works as you have it wired. Just tie the data line to Vcc with a 4.7Kohm resistor, and remove the series resistor between the sensor and the input pin.

cattledog:
The pullup resistor is necessary for parasitic power, but it also works as part of the bus management and communication protocol. It's possible that the internal pullup resistor of the Arduino will be sufficient, but I don't see either you or the library using INPUT_PULLUP as the pin mode.

I'm somewhat surprised that the sensor indeed works as you have it wired. Just tie the data line to Vcc with a 4.7Kohm resistor, and remove the series resistor between the sensor and the input pin.

Went to respond and took another look at my circuit. I did the diagram wrong, I think I did it as how you described. I have the 4.7k coming from Vcc to a rail with the sensor data pin and the arduino input pin. That makes much more sense, because you're right, it won't work with how the diagram is right now!

You have a bad error in the schematic with the relay connections. :astonished:

Hopefully you did not actually wire it that way!


You should not be powering this circuit via "Vin" or the "barrel jack". The on-board regulator is not capable - should not be used for projects where other devices (such as relays) are connected to the Arduino. Use a proper 5 V supply. :astonished:

Why do you have a potentiometer connected to the backlight? You only ever need three brightness levels, which can usually be controlled by the Arduino directly.

(Bright, dim, off. :grinning: )

Paul__B:
You have a bad error in the schematic with the relay connections. :astonished:

Hopefully you did not actually wire it that way!


You should not be powering this circuit via "Vin" or the "barrel jack". The on-board regulator is not capable - should not be used for projects where other devices (such as relays) are connected to the Arduino. Use a proper 5 V supply. :astonished:

Why do you have a potentiometer connected to the backlight? You only ever need three brightness levels, which can usually be controlled by the Arduino directly.

(Bright, dim, off. :grinning: )

Yea, I'm not actually 100% sure on how to wire the AC side of the relay yet. I am doing further research into that. Right now I just have it set up with LED's to know that it works.

The Vin is not powered with the port. I just wanted something to show to myself that i am using a wall adaptor.