Arduino fan controller code issues (LM35) - arduino

I got an issue with the PWM signal on the fan, it actually gets to 100% right away when it hits 21°C when it should be on 10%. I don't think it's a circuit issue, so any suggestions on the code ? I am pretty sure the problem is somewhere at the Map function, just can't seem to figure it out.
#include <LiquidCrystal.h>
LiquidCrystal lcd(12,11,5,4,3,2);
int tempPin = A1; // the output pin of LM35
int fan = 11; // the pin where fan is
int led = 8; // led pin
int temp;
int tempMin = 20; // the temperature to start the fan
int tempMax = 30; // the maximum temperature when fan is at 100%
int fanSpeed;
int fanLCD;
void setup() {
pinMode(fan, OUTPUT);
pinMode(led, OUTPUT);
pinMode(tempPin, INPUT);
lcd.begin(16,2);
Serial.begin(9600);
}
void loop() {
temp = readTemp(); // get the temperature
if(temp < tempMin) { // if temp is lower than minimum temp
fanSpeed = 0; // fan is not spinning
digitalWrite(fan, LOW);
}
if((temp >= tempMin) && (temp <= tempMax)) { // if temperature is higher than minimum temp
fanSpeed = map(temp, tempMin, tempMax, 115, 255); // the actual speed of fan
fanLCD = map(temp, tempMin, tempMax, 0, 100); // speed of fan to display on LCD
analogWrite(fan, fanSpeed); // spin the fan at the fanSpeed speed
}
if(temp > tempMax) { // if temp is higher than tempMax
digitalWrite(led, HIGH); // turn on led
} else { // else turn off led
digitalWrite(led, LOW);
}
lcd.print("TEMP: ");
lcd.print(temp,1); // display the temperature
lcd.print("C ");
lcd.setCursor(0,1); // move cursor to next line
lcd.print("FAN: ");
lcd.print(fanLCD); // display the fan speed
lcd.print("%");
delay(500);
lcd.clear();
}
int readTemp() { // get the temperature and convert it to celsius
temp = analogRead(tempPin);
return (temp * 0.48828125)-48;
}

Ok so apparently there was a problem with this specific pin, i tried another one (PWM), and it worked perfectly!

Related

Arduino for loop completely not functional

I am trying to send data from an accelerometer to Java from an Arduino. I am using delta time to limit it to sending only every 250 ms.
The problem is that all the Java program is reading is the first message sent in the setup() over and over.
I added a test Serial.write to check if the program is ever entering the delta time block, and it seems to be sending (or at least, reading) the first 2 characters of that message. The Arduino code is below.
#include <SparkFun_MMA8452Q.h>
int sleepPin = 7;
int stepPin = 6;
int buttonPin = 8;
int stepCount = 0;
boolean stepMode = true;
int delTime = 5000;
MMA8452Q accel; //accelerometer
void setup() {
Serial.begin(9600);
while (millis() < 4000); //wait so I can start java program
Serial.write("Connected");
//set pins
pinMode(sleepPin, OUTPUT);
pinMode(stepPin, OUTPUT);
pinMode(buttonPin, INPUT);
digitalWrite(stepPin, HIGH); //starts in step mode
delTime = millis() + 250;
}
void loop() {
if (digitalRead(buttonPin) == HIGH) stepMode = !stepMode;
if (millis() > delTime) {
Serial.write("delTime"); //test case
//set led's according to mode
if (stepMode) {
digitalWrite(stepPin, HIGH);
digitalWrite(sleepPin, LOW);
} else {
digitalWrite(stepPin, HIGH);
digitalWrite(sleepPin, LOW);
}
//create string to store data
String data = "";
if (stepMode) data += "s"; //s is step mode key
else data += "z"; //z is sleep mode key
//add actual reading stuff
data += String(accel.getX()) + "," + String(accel.getY());
Serial.write(data.c_str()); //send the lad over
}
}
The Java side is nearly identical (sans the conditions of an if statement, but it doesn't matter because if it doesn't meet the statement it just prints what it sees) to a functional program for serial communication that I've used before. I can include it if necessary though.
The Java console output appears as:
Connected
de
Connected
de
Connected
de
where a new iteration appears about once a second. What am I doing that prevents the Arduino from sending the data?
Not a proper answer yet, more of a test, but I couldn't fit it in a comment.
Changes made:
delTime is now an unsigned long int;
delTime is now reset at the end of the loop();
String object and manipulations were replaced by heap-friendlier code.
Added accel.begin();
Let me know if this works for you, and if not, where it complains. Haven't fully tested the code. You could also try replacing accel.getX() and accel.getY() with numbers; they return short ints, I think.
BTW the button needs debouncing.
#include <SparkFun_MMA8452Q.h>
int sleepPin = 7;
int stepPin = 6;
int buttonPin = 8;
boolean stepMode = true;
unsigned long int delTime = 0;
MMA8452Q accel; //accelerometer
void setup(){
Serial.begin(9600);
while(millis() < 4000); //wait so I can start java program
Serial.write("Connected");
//set pins
pinMode(sleepPin, OUTPUT);
pinMode(stepPin, OUTPUT);
pinMode(buttonPin, INPUT);
accel.begin();
digitalWrite(stepPin, HIGH); //starts in step mode
delTime = millis() + 250;
}
void loop() {
char str[15];
if (digitalRead(buttonPin) == HIGH)
stepMode = !stepMode;
if (millis() > delTime) {
//set led's according to mode
if (stepMode) {
digitalWrite(stepPin, HIGH);
digitalWrite(sleepPin, LOW);
Serial.write('s');
} else {
digitalWrite(stepPin, HIGH);
digitalWrite(sleepPin, LOW);
Serial.write('z');
}
sprintf(str, "%d", accel.getX());
Serial.write(str);
Serial.write(',');
sprintf(str, "%d", accel.getY());
Serial.write(str);
Serial.write('\n');
delTime = millis() + 250;
}
}

Arduino as gateopener

I am new to codeing arduino.
I have a project which is about useing an arduino as a gate opener, but only when the temperature gets above 24 degrees.
The problem is how do i get the arduino to send a signal to the relay to open, but only once?
I tried with if statements and trying under there to run with some while(1); but that seems to end the whole script. so that does not do what i want it to..
```
float temp;
int tempPin = A0;
int Relay1 = 13;
bool ronce = false;
void setup() {
Serial.begin(9600);
pinMode(Relay1,OUTPUT);
}
void loop() {
delay(500);
temp = analogRead(tempPin);
temp = temp * 0.48828125;
Serial.print(temp);
if(temp>24){
ronce == true;
Serial.println(" Temp over 24 degree");
if (ronce = true){
Serial.println(" Ronce is true.");
while(1){
Serial.println("runOnce");
digitalWrite(Relay1,HIGH);
delay(500);
digitalWrite(Relay1,LOW);
}
}
}
else {
ronce == false;
Serial.println(" failure");
}
}
I want it to send a signal at 24 degrees to the relay to go on NC & ground and then turn off after 500 ms ish.
then it should not turn on again until when it gets below 24 degrees again.
The output turns out between 20-37 degrees so the LM35 does as i want it to, it is just the code.
You just need to create a read function and then read it until it reaches above 24, then just turn on relay and wait again until the temp gets below 24.
int tempPin = A0;
int Relay1 = 13;
float read_temp()
{
float sum = 0;
float temp;
for (int i = 0; i < 500; i++)
{
sum += analogRead(tempPin);
delayMicroseconds(100);
}
temp = sum / 500;
temp = temp * 0.48828125;
return temp;
}
void setup()
{
Serial.begin(9600);
pinMode(Relay1, OUTPUT);
}
void loop()
{
if (read_temp() > 24)
{
Serial.println("Temp over 24 degree");
digitalWrite(Relay1, HIGH);
delay(500);
digitalWrite(Relay1, LOW);
// wait until temp reach below 23.5
while (read_temp() > 23.5)
;
}
}

I can't fully understand why the program isn't working - LCD Screen problems and more

I'm working on a project for an automatic Malteser (or similar product) dispenser and I got the code to work, but after leaving it it for a bit, the screen played up and it won't work properly. The LED also is always on and it can seem to move on from the Setup
I have tried:
searching the code for faults
checking the wiring
redoing the wiring in case i missed something
Code:
#include <Servo.h>
#include <DS3231.h>
#include <Wire.h>
#include <LiquidCrystal.h>
DS3231 Clock;
bool Century = false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;
int second, minute, hour, date, month, year, temp;
int button = 8;
int maltesersEaten = 0;
int lastEatenSe = 0;
int lastEatenMi = 0;
int lastEatenHo = 0;
int lastEatenDa = 0;
int lastEatenMo = 0;
int lastEatenYe = 0;
bool eat;
int ledPin = 10;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Servo myServo;
byte degree[8] = {
B00100,
B01010,
B00100,
B00000,
B00000,
B00000,
B00000,
};
void setup() {
**lcd.createChar(0, degree);
lcd.begin(16, 2);
// Print a message to the LCD
lcd.print("INITIALIZING");
// Start the I2C interface
Wire.begin();
// Start the serial interface
Serial.begin(9600);
pinMode(button, INPUT);
myServo.attach(9);**
myServo.write(10);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(1000);
lcd.clear();
}
void getData() {
second = Clock.getSecond();
minute = Clock.getMinute();
hour = Clock.getHour(h12, PM);
date = Clock.getDate();
month = Clock.getMonth(Century), DEC;
year = Clock.getYear();
temp = Clock.getTemperature();
lcd.setCursor(0, 0);
lcd.print(hour);
lcd.print(":");
lcd.print(minute);
lcd.print(":");
lcd.print(second);
lcd.setCursor(0, 1);
lcd.print(date);
lcd.print(",");
lcd.print(month);
lcd.print(",");
lcd.print(year);
lcd.setCursor(9, 0);
lcd.print(temp);
lcd.write(byte(0));
lcd.print("C");
lcd.setCursor(9,1);
lcd.print("ATE:");
lcd.print(maltesersEaten);
}
void mE() {
maltesersEaten = (maltesersEaten + 1);
lastEatenSe = second;
lastEatenMi = minute;
lastEatenHo = hour;
lastEatenDa = date;
lastEatenMo = month;
lastEatenYe = year;
}
void check() {
lcd.clear();
lcd.print("-Last Malteser-");
delay(500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(hour);
lcd.print(":");
lcd.print(minute);
lcd.print(":");
lcd.print(second);
lcd.setCursor(0, 1);
lcd.print("Eaten: ");
lcd.print(maltesersEaten);
delay(5000);
lcd.clear();
}
void loop() {
if (digitalRead(button) == LOW) {
digitalWrite(ledPin, HIGH);
myServo.write(170);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("---- Have A ----");
lcd.setCursor(0, 1);
lcd.print(" Malteser ");
delay(5000);
myServo.write(10);
lcd.clear();
check();
mE();
digitalWrite(ledPin, LOW);
}
else if (digitalRead(button) == HIGH) {
getData();
}
}
The desired effect would be the screen produces a message, the LED flashes, then it shows the time, date and temperature of the room, as well as how many Maltesers have been eaten. then when the button is pressed, the servo moves, the LED turns on and the LCD changes through a few different screens, then it returns to the time, date, temp, and number of Maltesers eaten. However the actual result is that the LED turns on permanently, the LCD produces two solid blocks and nothing else, and the servo goes limp, when I press the button nothing changes. I think the problem is in the setup if that is of nay help.
In the program you call the function: check(). In there is a five second delay and in the loop there is another 5s delay. Could it be that you always press the button when the delay is on. Then the program would not notice that the button was pressed and continues with the loop again. This would also explain why the led won't turn off because it is turned on again right away.
To test if this is the case just hold the button down for at least 10s and sea if it works.
If this is the case, to fix this problem try working with an interrupt.
See documentation here: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

no breadboard LED output

I'm making a simple temperature sensor to light one of two LEDs depending on the temperature.
For some reason the LED output only blinks the onboard LED (pin 13 on the Edison) once.
My temperature output is working fine, but I'm not sure why my code is working incorrectly.
Photo of the wiring here.
int temppin = 0;
int ledhigh = 7;
int ledlow = 8;
void setup()
{
Serial.begin(9600);
pinMode(temppin, INPUT);
pinMode(ledhigh, OUTPUT);
pinMode(ledlow, OUTPUT);
}
void loop()
{
int tempout = analogRead(temppin);
float volts = tempout * 5.0;
volts /= 1024.0;
float temp = (volts - 0.5) * 100 ;
Serial.print(temp); Serial.println(" celsius");
if (temp > 0){
Serial.print("high temp =");
digitalWrite(ledhigh, HIGH);
} else {digitalWrite(ledlow, HIGH);
Serial.print("low temp");
}
delay(3000);
}
The problem is probably that you're trying to use the analog input pins as output. You need to use the digital pins.
As explained in this video:
https://youtu.be/BtLwoNJ6klE?t=50s

Arduino, if else LED "stuck"

So the code is not working properply, there are two leds that wont turn off "highliten" the problem. when i run the Else part of the program. i want to turn them off in the else part. :)
include
byte ledPin[] = {8, 9, 10, 11, 12, 13}; //--------------------------------.
int ledDelay; // Del 1
int direction = 1;
int currentLED = 0;
unsigned long changeTime;
int potPin = 0;
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
int va;
void setup()
{
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, INPUT);
myservo.attach(3); // attaches the servo on pin 9 to the servo object
Serial.begin(9600);
for (int x=0; x<6; x++) {
pinMode(ledPin[x], OUTPUT); }
changeTime = millis();
}
void loop() {
int on = digitalRead(6);
if (on == HIGH)
{
myservo.attach(3);
// Here is the problem!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if va < 523)
{
digitalWrite(5, HIGH);
}
else if (va > 555)
{
digitalWrite(4, HIGH);
}
else
{
digitalWrite(4, LOW);
digitalWrite(5, LOW);
}
// Here is the problem!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
va = analogRead(potPin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(va, 0, 1023, 0, 179); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(1); // waits for the servo to get there
}
else
{
myservo.detach();
digitalWrite(5, LOW);
digitalWrite(4, LOW);
ledDelay = analogRead(potPin) / 4;
if ((millis() - changeTime) > ledDelay)
{
changeLED();
changeTime = millis();
}
}
}
void changeLED() {
for (int x=0; x<6; x++)
{
digitalWrite(ledPin[x], LOW);
}
digitalWrite(ledPin[currentLED], HIGH);
currentLED += direction;
if (currentLED == 6) {direction = -1;}
if (currentLED == 0) {direction = 1;}
}
in advance Thank you!
Right at the end of the sketch you have the following line:
if (currentLED == 6) { direction = -1; }
I think, without actually running the program, that the problem is here. In the previous line you have added one to the value of currentLED and you are checking to see if you have gone off the end of the ledPin array. You change the direction but you don't reset the currentLED position to be back inside the ledPin range.
The next time changeLED is called it tries to call digitalWrite(ledPin[currentLED], HIGH); but the value of currentLED is 6, which is outside the ledPin array. The Arduino probably gets upset at this point.
I think you simply need to change the statement to check whether currentLED == 5 rather than 6. This will mean that next time that changeLED is called the last LED will be turned on and the value of currentLED will be decremented (direction == -1), keeping it inside the ledPin range.

Resources