ATTINY45 Arduino IDE and millies() problem - Page 1
Forum section: electronics / general

author: jct
author_rank: Contributor
timestamp: June 02, 2016, 04:01:01 pm
content: I'm an old hat but total noob to coding (which is evident from the effort below).Everything is working as it should, apart from the 7200000ms (2h) when pot is adjusted to high side on pin 2 (PB3) . The output pin 3 (PB4) is supposed to stay low for 2h and then go high for 2h, but it only stays low for 50 min and then go high for 50 min. I am against a brick wall here and either don't understand the millis() function and/or don't understand anything at all. Anyone kind enough to look at this noob's code and advise what is wrong(I assume that something is wrong with this line: ["interval = map(interval, 0, 1023, 1800000UL, 7200000UL); // min 30min to max 120min")?PS: At minimum setting (pot adjusted to low side), it works 100%; 30 min low, 30 min high./* Air Scrubber Control V1.3Turns On and Off Heater Relay (t-On = t-Off) ATtiny45-20SUThe amount of time the Relay will be On and Off depends on the valueobtained by analogRead() - 30 to 120min (1,800,000 to 7,200,000ms)Extend the actuator at time Heater Relay switch On, and retractthe actuator at time Relay switch OffBuzzer beep for 200ms when actuator extends and/or retractsINPUT: 100k pot - pin 2 (PB3)OUTPUT: Heater SPCO Relay - pin 3 (PB4)Halfbridge Signal 1 - pin 5 (PB0)Halfbridge Signal 2 - pin 6 (PB1)Buzzer - pin 7 (PB2)01/06/2016size: 1,760 bytes*/// constants won't change. Used here to set pin numbers:const int potPin = 3; // select the input pin for the 100k potconst int relayPin = 4; // select the pin for the SPCO Relayconst int signalPin1 = 0; // select pin for Halfbridge Signal 1 (extend)const int signalPin2 = 1; // select pin for Halfbridge Signal 2 (retract)const int buzPin = 2; // select pin for buzzer// Variables will change:int relayState = LOW; // relayState used to set the Relayunsigned long previousMillis = 0; // will store last time Relay was updatedunsigned long interval = 0; // variable to store the value coming from the 100k potvoid setup() {pinMode(relayPin, OUTPUT); // declare the Relay pin as an OUTPUTpinMode(signalPin1, OUTPUT); // declare the bridge Signal 1 pin as an OUTPUTpinMode(signalPin2, OUTPUT); // declare the bridge Signal 2 pin as an OUTPUTpinMode(buzPin, OUTPUT); // declare the buzzer pin as an OUTPUT// make sure actuator is retracteddigitalWrite(1, HIGH); // Turn on Signal 2 on Pin 6 (PB1)delay(750); // wait for 750msdigitalWrite(1, LOW); // Turn off Signal 2 on Pin 6 (PB1)digitalWrite(2, HIGH); // Turn on buzzer on Pin 7 (PB2)delay(200); // wait for 200msdigitalWrite(2, LOW); // Turn off buzzer on Pin 7 (PB2)}void loop() {unsigned long interval = analogRead(potPin); // read the value from the pot// interval = map(interval, 0, 1023, 10000, 2000); // min 2 to max 10s - for testing// interval = map(interval, 0, 1023, 1800000UL, 3600000UL); // min 30min to max 60mininterval = map(interval, 0, 1023, 1800000UL, 7200000UL); // min 30min to max 120minunsigned long currentMillis = millis(); // will store last time Relay was updatedif (currentMillis - previousMillis >= interval) {// save the last time Relay was switchedpreviousMillis = currentMillis;// if the Relay is off turn it on and vice-versa:if (relayState == LOW) {relayState = HIGH;digitalWrite(0, HIGH); // Turn on Signal 1 on Pin 5 (PB0)delay(750); // wait for 750msdigitalWrite(0, LOW); // Turn off Signal 1 on Pin 5 (PB0)digitalWrite(2, HIGH); // Turn on buzzer on Pin 7 (PB2)delay(200); // wait for 200msdigitalWrite(2, LOW); // Turn off buzzer on Pin 7 (PB2)} else {relayState = LOW;digitalWrite(1, HIGH); // Turn on Signal 2 on Pin 6 (PB1)delay(750); // wait for 750msdigitalWrite(1, LOW); // Turn off Signal 2 on Pin 6 (PB1)digitalWrite(2, HIGH); // Turn on buzzer on Pin 7 (PB2)delay(200); // wait for 200msdigitalWrite(2, LOW); // Turn off buzzer on Pin 7 (PB2)}digitalWrite(relayPin, relayState); // set the Relay with the relayState of the variable}}

author: dannyf
author_rank: Super Contributor
timestamp: June 02, 2016, 04:24:28 pm
content: There are two "interval" defined.Your problem sounds like over flow or type casting.Wheneveer you fllip the relay, you should record it's time and you should test against that. That means sthe use of global variables, or static variables..

author: jct
author_rank: Contributor
timestamp: June 02, 2016, 04:28:58 pm
content: Thanks @dannyf, I will look up those terms and investigate (need to, because this is a totally new world to me).

author: edavid
author_rank: Super Contributor
timestamp: June 02, 2016, 04:32:03 pm
content: Looks like map() is overflowing internally. A quick fix would be to do the map() in terms of minutes, then convert to milliseconds. That would also make the code more readable.

author: jct
author_rank: Contributor
timestamp: June 02, 2016, 04:35:58 pm
content: Thanks @edavid, I will look up how to do that and see if it solves my problem.

author: jct
author_rank: Contributor
timestamp: June 06, 2016, 07:10:03 am
content: After many hours of reading and experimentation over the past weekend, the issue is now solved.It seems (through experimentation), that the maximum reliable value map() function can handle is only 2880000UL (which coincides with my original problem of only getting ~50 min instead of 120 min).Changed the specific line in code from map() function to a simple equation - I'm sure there are much more elegant and/or better ways to do it, but it works for me.From: interval = map(interval, 0, 1023, 1800000UL, 7200000UL); // min 30min to max 120minTo: interval = 1800000UL + (interval * (5400000UL / 1023)); // min 30min to max 120minAnother interesting observation; code size are now only1484bytes compared to the previous1760bytes.

author: dannyf
author_rank: Super Contributor
timestamp: June 06, 2016, 10:21:41 am
content: The cause is the overflow in mapping your input to the desired range.One way to get around it is to map to seconds, minutes or even hours.