-1

I have 2 sketches that control a fan using Arduino UNO, that I try to combine. The 1st is a timer, that turns a pin ON and OFF for a determined period of time. The pin signal drives a MOSFET that in turn switches a small fan ON and OFF. Since I need to control the speed of the motor, I would rather use the PWM control, however I am not sure how I can apply the timer since analogWrite command refers to a pin and value. Thanks

timer code:

const byte relayPin = 6; // relay module on pin 6
const byte monitorPin = 13; // builtin LED output
const unsigned long interval_1 = 1000UL * 15, interval_2 = 1000UL * 15; // ON timer + OFF timer in milliseconds
unsigned long currentMillis, previousMillis = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, HIGH); // relay OFF
  pinMode(monitorPin, OUTPUT);
  digitalWrite(monitorPin, LOW); // LED off
}

void loop() {
  // put your main code here, to run repeatedly:
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval_1)
  {
    digitalWrite(relayPin, LOW); // relay ON
    digitalWrite(monitorPin, LOW); // LED on
  }
  if (currentMillis - previousMillis >= (interval_1 + interval_2))
  {
    digitalWrite(relayPin, HIGH); // relay OFF
    digitalWrite(monitorPin, HIGH); // LED off
    previousMillis = currentMillis; // reset
  }

PWM code:

int PWMControl= 6;
int PWM_Input = A0;

int PWM_Value = 0 ;

void setup() {
  pinMode(PWMControl, OUTPUT);
  pinMode(PWM_Input, INPUT);
}

void loop() 
{
  PWM_Value = analogRead(PWM_Input);
  PWM_Value = map(PWM_Value, 0, 1023, 0, 255);
  analogWrite(PWMControl, PWM_Value);
}
Edgar Bonet
  • 43,033
  • 4
  • 38
  • 76
kwhunter
  • 23
  • 10

2 Answers2

1

If I understand correctly, this is what you want to do:

  1. Fan + led off for 15s
  2. Fan on (speed determined by A0) + led on for 15s
  3. Repeat

clearly defining your goal in english can help with coding, so I hope I guessed right.

here's my suggestion for your code

 const byte controlPin = 6; // MOSFET on pin 6
 const byte monitorPin = 13; // builtin LED output
 const unsigned long interval_1 = 1000UL * 15, interval_2 = 1000UL * 15; // ON timer + OFF timer in milliseconds
 unsigned long currentMillis, previousMillis = 0;
 int PWM_Input = A0;
 int PWM_Value = 0 ;

 // setting pin direction and default state
 void setup() {
   pinMode(controlPin, OUTPUT);
   digitalWrite(controlPin, HIGH); // MOSFET OFF
   pinMode(monitorPin, OUTPUT);
   digitalWrite(monitorPin, LOW); // LED off
 }

 // run fan for a while, then stop fan for a while
 void loop() {

   currentMillis = millis();

   //fan on, led on, both signals active low
   if (currentMillis - previousMillis >= interval_1){
       PWM_Value = analogRead(PWM_Input);
       PWM_Value = map(PWM_Value, 0, 1023, 0, 255);
       analogWrite(PWMControl, PWM_Value);
       digitalWrite(monitorPin, LOW);
   }

   //fan off, led off, reset timing
   if (currentMillis - previousMillis >= (interval_1 + interval_2)){
      digitalWrite(controlPin, HIGH); // MOSFET OFF
      digitalWrite(monitorPin, HIGH); // LED off
      previousMillis = currentMillis; // reset
   }
 }

There are still issues I can with this code:

  1. You did not tell us what type of MOSFET you are using, so I can't tell if it is actually active low
  2. I believe that the LED on most arduino boards (pin 13) is active high, so that's probably wrong
  3. Don't forget comments. I find comments more useful for a block of code than for a single line, but you can do both if you want ;)
  4. I find your code convoluted regarding millis logic, for me it would be more logical to have something along the lines of:

     current = millis()-previous
     if current < interval1 
        fan off
     elseif current < inteval1+interval2
        fan on
     else
        previous = millis() 
    

It would be more readable for a human, the result on the arduino would be similar.

MAB
  • 111
  • 3
  • you've got it right; I use a BUZ11 N-channel MOSFET to control the fan. The code as it is now, works fine: the LED is on only when the fan is on. I tried replacing the digital Write with the analogWrite as suggested but it didn't work so that's why I posted the code here. It's obvious I'm not an experienced programmer... – kwhunter Jul 02 '19 at 21:06
  • @kwhunter have you tried to use the Serial monitor to make sure your initial program does what you think it does? It's extremely useful to debug arduino code. A few thing to monitor: does the fan turn on/off when you think your code turns it on/off. You also should monitor the PWM_Value before and after map, to make sure you are feeding analogWrite with the proper parameter. These would be the first things I look at. – MAB Jul 03 '19 at 00:17
  • No I did not, application not critical; for the record, I use the fan to move around the air in the Humidor for the temperature and humidity to even out. Current setting is 1 minute ON and 15 minutes off. – kwhunter Jul 03 '19 at 16:51
  • Thinking back at my note#4, the resulting program would actually be different, since while the fan is on, it would immediately react to a change on A0, which is arguably better. your initial program with the on-off structure would have been easily implemented with delay() - also if you plan to run this program for a very long time, you will have an unexpected behavior when millis() overflows. – MAB Jul 03 '19 at 17:14
  • I made some edits to your program since the fan was ON all the time and when timer 2 kicked in it changed speed since A0 controlled it; now it works as it should, thanks. Aren't the millis() reset each cycle? if not what can I do to prevent the overflow? – kwhunter Jul 03 '19 at 17:50
  • no, millis() returns the number of milliseconds since you powered-up the board, it keeps counting until it reaches its max value, then goes back to zero (after ~50 days according to arduino documentation: https://www.arduino.cc/reference/en/language/functions/time/millis/). you can guard against it with an if statement, or some clever math, there are examples you can easily find, this is NOT an unusual thing. also, if that's been helpful to you, consider up-voting and select the answer. If you think I should change something specific in the code I gave in my answer, I can do that too. – MAB Jul 03 '19 at 20:40
  • sorry MAB, I cannot vote since I do not have enough privileges. The code is Ok, I didn't know you can turn on an output with an analogWrite and turn it off with a digitalWrite... Someone wrote another code for me, but it is a more advanced use of commands and therefore not as easy to add the PWM function, in my opinion. I will google for the millis overflow; if I cannot handle, I will just turn the board off every week... – kwhunter Jul 03 '19 at 21:08
  • functionally, digitalWrite(LOW) is equivalent to analogWrite(0), digitalWrite(HIGH) is equivalent to analogWrite(255) if the pin is PWM capable. I can only encourage you to use https://www.arduino.cc/reference/en/ more, it has a lot of useful information. – MAB Jul 03 '19 at 22:47
0

Don't think of what you have as a "timer". That's not what it really is. What you have is a loop function that repeats itself thousands of times per second and an if statement that asks "is it time to do this yet". So if you want to use analogWrite instead of digitalWrite when it is time to do that thing then use analogWrite instead. It doesn't change your timing setup one bit. Just replace the digitalWrite calls with analogWrite calls. If you want to read your pot at the same time then put that in there as well. Basically everything inside the block of code controlled by that if statement is going to happen every time that interval passes no matter what it is that you put there. If you want something to print every interval then you could put a print statement in there. If you want it to call some custom function every interval then call that function in there. There's nothing special about that way of timing that only works with digitalWrite.

Delta_G
  • 3,270
  • 2
  • 10
  • 24