30 Second Timer + LED Display + Pager Motor HELP!!

Thanks for the replies BigMike & mem.

Mike, your code seems very easy and effective in terms of what I need to do. It was clear for the most part, although I had a couple of questions

a) what is the crtMillis value going to be when it loops through the first time? cause it seems like as soon as the value of crtMillis changes, you set it back to 0.

b) I didn't quite understand the TimerVal --; thing. Is it an int, I presume so. How does it know how much time has passed? Do I set it equal to another millis function?

Mem, I think your code makes a lot of sense. I just wanted to know in slight detail of some the functions that your library has.

a) I am guessing the Timer1.value sets the value of the first time in Seconds?

b) Does it run through the setup each time? I guess once you define the value in the setup, it checks if it's actually equal to that.

Finally, whatever the time it might be, I also need to run a 2 digit LED display. I already checked some inbuilt libraries, but I had a hard time understanding them. I just need it do a countdown from 30 seconds. Thus every second it counts, I need it change the display to 30, 29... and reset it back to 30 once it's matured.

Again, I sincerely appreciate your help. They're pretty inane questions, but I just have a hard time understanding it.

EDIT - Would you able to upload the initial Clock library somewhere so I can use it? Also, wouldn't the delay function cause the whole code to stop for a the defined time?

Much respect.

I am guessing the Timer1.value sets the value of the first time in Seconds?
Yes, the event hander for Timer1 (OnTimer1Tick) will be called 5 seconds after Timer1 is enabled

Does it run through the setup each time? I guess once you define the value in the setup, it checks if it's actually equal to that.
Once the value is set it will be maintained until it is explicitly set to something else. The timer will actually continue to trigger every 5 seconds unless it is disabled, which is why it is disabled for your applicaiton when it matures, and re-enabled when a trigger arrives on the serial port.

Finally, whatever the time it might be, I also need to run a 2 digit LED display. I already checked some inbuilt libraries, but I had a hard time understanding them. I just need it do a countdown from 30 seconds. Thus every second it counts, I need it change the display to 30, 29... and reset it back to 30 once it's matured.

I would implement this using a timer with a value of 1 second. Each time the event handler is called I would decrement a counter initially set to 30 by 1. You could display this number on the lcd and turn the motor off when it gets to 0.
But, if this is the functionality you want, it may just be easier to do it using the millis counter, as per Mikes proposal.

Also, wouldn't the delay function cause the whole code to stop for a the defined time?
Calling Clock.Delay() blocks the foreground sketch for the given number of millis (one millisecond per loop in the example sketch) but the underlying code in the Clock.delay function is constantly checking the timer states to see if a timer has matured.

My suggestion if you have only a single delay going on at one time is to try Mikes approach first. But I will get you the code if you are comfortable modifying your copy of wiring.c

Thanks for the replies BigMike & mem.

Mike, your code seems very easy and effective in terms of what I need to do. It was clear for the most part, although I had a couple of questions

a) what is the crtMillis value going to be when it loops through the first time? cause it seems like as soon as the value of crtMillis changes, you set it back to 0.

Lack of comments and poorly named variables makes it harder to understand :slight_smile:

However, I can't see where I'm setting crtMilli back to zero. Each time through the loop I grab the current value of the millisecond counter using the line crtMilli = millis(); If it differs from the previous value (prvMilli) then at least one milli second has passed.

Doing a test for different (!=) rather then just greater than means that you don't need to fix the millis() function timer rollover bug mem mentions.

b) I didn't quite understand the TimerVal --; thing. Is it an int, I presume so. How does it know how much time has passed? Do I set it equal to another millis function?

TimerVal--; is a decrement by one instruction. Equivalent to TimerVal = TimerVal - 1;. There are pre- and post- decrement and increment instructions: i++; ++i; i-- and --i;

So the timer works by counting down to zero in milliseconds.

Regards,

Mike

Big Mike, I managed to figure out what everything stands for and actually have MOSTLY everything running. Thanks for the help again (mem & yourself) Here's my code:

int rxPin = 0;
int txPin = 1;
int motPin = 2;
int ledPin = 13;

unsigned long PreviousTime = 0;
unsigned long CurrentTime = 0;
int TimerValue = 0;
int Counter = 30;

void setup() {
// define pin modes for tx, rx, led pins:
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
pinMode(motPin, OUTPUT);
pinMode(ledPin, OUTPUT);
for (int i = 3; i< 12; i++){
pinMode(i, OUTPUT);
}
// set the data rate for the SoftwareSerial port
Serial.begin(9600);
}

void loop() {
CurrentTime = millis();
if(CurrentTime != PreviousTime){
PreviousTime = CurrentTime;
if (Serial.available() > 0){
char someChar = Serial.read();
Serial.print(someChar);
if (someChar == 'a'){
motor(ledPin);
motor(motPin);
}
if (someChar == 'b'){
TimerValue = 1000;
Counter = 30;
}
}
TimerValue --;
if(TimerValue <= 0){
TimerValue = 1000;
Serial.println(Counter);
Display(Counter);
if(Counter <= 0){
Counter = 31;
}
Counter --;
}
}
}

void motor(int pinNum)
{
digitalWrite(pinNum, HIGH);
delayMicroseconds(5000);
digitalWrite(pinNum, LOW);
}

void Display(int number){
TurnOffDisp();
int ones;
int tens;
ones = number%10;
number = number/10;
tens = number%10;

if(ones==0) {
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
} .....
}

Final question, I need to drive 2 LED Displays (7-segment, common anode) with the countdown running on it. I managed to get one of the digits running (ones) but realized that I don't have enough pins to run the second digit (tens).

I googled a couple of things and read about multilexing/charlieplexing. This requires me to use 2 transistors (1 for the CA pin of each display) which require 2 pins and 7 other pins that run in parallel to the 2 LED displays. Thus, requiring me to use only 9 pins. I also read that it quickly keeps scanning and refreshing the 2 digits fast enough so that the naked eye cannot see if one of them is off.

I just wanted a guideline or a brief idea of what my code should look like. Currently, I am asking my Arduino to change the Pin state based on the number it reads.

Thanks in advance,
Shubs

If you need 7 outputs for each of the two lEDs and one for the motor you may have enough pins without multiplexing. You can use the six analog pins as digital outputs 14-19.

While I was reading over my code, I read that I have used delayMicroseconds() in the motor function.
Is there any way that I can use the millis() to prevent it from delaying the code?

void motor(int pinNum)
{
digitalWrite(pinNum, HIGH);
delayMicroseconds(5000);
digitalWrite(pinNum, LOW);
}

I was hoping that I could shove in another millis() and modify it as follows

void motor(int pinNum){ 
unsigned long time = 0;
  time = millis();
  if (time == 0){
    digitalWrite(pinNum, HIGH);
  }
  if (time >= 5000){
  digialWrite(pinNum, LOW);
  time = 0;
  }
}

Although, I have a feeling that 2 millis functions might cause a slight problem. Please shed some light.

Regards,
Shubs

You can simply change
delayMicroseconds(5000); // delay 5000 microseconds = 5milliseconds
to
delay(5); // delay 5 milliseconds

If you need 7 outputs for each of the two lEDs and one for the motor you may have enough pins without multiplexing. You can use the six analog pins as digital outputs 14-19.

Even on the Arduino Mini?
Analog Pin 0 = Digital I/O Pin 14?

You can simply change
delayMicroseconds(5000); // delay 5000 microseconds = 5milliseconds
to
delay(5); // delay 5 milliseconds

But that would off set my CurrentTime & PreviousTime by 5 milliseconds correct? Because it would stop the execution of the rest of the code.

Even on the Arduino Mini? Analog Pin 0 = Digital I/O Pin 14?
according to this page Arduino Reference - Arduino Reference, you have two extra analog ports on the mini. I would think pins 14-19 work as digital pins on the mini but not analog pins 6 & 7.

Try it and see, set pins 14-21 as outputs and do a digitalWrite to see if it lights an LED on those pins.

But that would off set my CurrentTime & PreviousTime by 5 milliseconds correct? Because it would stop the execution of the rest of the code.

Execution will be blocked when calling delayMicroseconds or delay. If this is not what you want then you need to something a little more complicated. Could you clarify what you want to happen if you get a trigger from the serial port while a previous trigger is still counting down.

But that would off set my CurrentTime & PreviousTime by 5 milliseconds correct? Because it would stop the execution of the rest of the code.

Execution will be blocked when calling delayMicroseconds or delay. If this is not what you want then you need to something a little more complicated. Could you clarify what you want to happen if you get a trigger from the serial port while a previous trigger is still counting down.

If I execute the motor() function, it will cause the motor to vibrate, when it is being executed the 30 second timer would effectively become a 30 + 5 millisecond timer. Every time the pager motor vibrates, it's going to add 0.5 seconds to the difference between CurrentTime & PreviousTime.

Since It will be receiving a lot of inputs to activate the motor function, the error would become too big, hence I need both the motor execution and timer function to be dependent on only one variable, that is time.

I hope that it is clear enough. I think my team has NEARLY fine tuned everything that we want from the device, now the only thing we have left to do is test it out.

Thanks for your help.

The millis function returns the number of milliseconds since the Arduino started. So when you read this value into a variable holding the start time, you can get the amount of time elapsed by subtracting the current millis reading from the start time. It won't matter if you delay for 5 milliseconds as long as the delay finishes before the desired end time, the calculation for start millisconds – millis will return the elapsed time to the nearest millisecond.

In other words, your timings will not be increased by this 5ms delay.

Sorry if I've confused you, but the pager motor vibration length is supposed to be half a second so it's 500 milliseconds. I could make the timing slightly smaller but I want refrain from that.

We've set the TimerValue = 1000 that's 1 second.
If the delay on the motor function is 500 and each time it receives an execution command then
CurrentTime = PreviousTime + 500 am I Correct? Because of the delay.
Thus, if I had 4 consecutive beats, my TimerValue that should have decreased by 2x TimerValue--, will only be reduced once. Right?

You have no idea how much I appreciate your help!!!!

While I was reading over my code, I read that I have used delayMicroseconds() in the motor function.
Is there any way that I can use the millis() to prevent it from delaying the code?

void motor(int pinNum)
{
digitalWrite(pinNum, HIGH);
delayMicroseconds(5000);
digitalWrite(pinNum, LOW);
}

Shubs,

As 5000 micro seconds is 5milliseconds, that can be implemented as a state machine.

Define the states and set up two variables, one to hold the state and one to hold the time.

#define mtrStable = 0
#define mtrOn = 1
#define mtrOff = 2
var byte mtrState;
var byte mtrCount;

mtrState = mtrStable;
mtrCount = 0;

Then in the loop, instead of calling the motor() function, change the motor state variable:

if (someChar == 'a'){ 

mtrState = mtrOn;
 mtrCount = 500;
}




then later check the motor state variable:


if (mtrState == mtrOn){
 digitalWrite(motPIN, HIGH);
 mtrCount = 500;
 mtrCount --;

if (mtrCount <= 0){
 // time's up, so stop
 mtrState == mtrOff;
 }
}
if (mtrState == mtrOff){
 digitalWrite(motPIN, LOW);
 mtrState = mtrStable;
}
...




Something like that should work.

Regards,

Mike

Sorry if I've confused you, but the pager motor vibration length is supposed to be half a second so it's 500 milliseconds. I could make the timing slightly smaller but I want refrain from that.

Ah - so in my previous post, change the mtrCount variable to an int and set it to 500 in the loop.

Mike

That's exactly the code I need to implement. Thanks BigMike. Seems like I'm sorted for now.

I can only hope that all of this works when we put it together. I'll keep you guys posted.

Thanks again!

Should the second part of the code, the checking of the state of the motor, be in the main loop or should I modify my motor function?

void motor(int counter){

mtrCount = counter;

if (mtrState == mtrOn){
  digitalWrite(motPIN, HIGH); 
  mtrCount --;

  if (mtrCount <= 0){
  // time's up, so stop
  mtrState == mtrOff;
  }
}
if (mtrState == mtrOff){
  digitalWrite(motPIN, LOW);
  mtrState = mtrStable;
}
...

It should be in the main loop. The motor() function is not needed anymore.

Mike

I have another problem.

I am trying to use Serial communication to receive data on the Arduino (Pin 0/Pin 1). The other prototyping board is a VX-Mega 128 and it is coded to send characters 'a' and 'b' over the air using a RF serial link that I bought from Sparkfun.

The receiver module is connected to my RX pin on the Arduino, despite baud rates being set the same, my arduino does not receive the characters. I even tried a wired method of communication but that didn't work either.

I tried Serial communication between two arduinos (MINI & Diecemilia) and that didn't work either. I've looked at the software serial library, tried to run that too, but it's giving me funky errors.

We've got everything working for the most part, besides the communication. USB communication, like I said, works fine. Just the RF or wired communication between two MCU is a problem.