I have done a lot of research but would appreciate some opinions on general approaches. I'm working on a program to do the following:
Read a digital input via interrupts (events occurring up to 50 Hz)
Perform an action with a run-time variable time delay
2a. Action consists of
commanding an output ON
waiting for user specified time
commanding output OFF
Overall the logic is simple, however the issue I'm having is in the physical system, the next trigger event occurs before the first action is initiated. I think I need some type of event management or queuing system, but perhaps I'm overthinking it. Essentially I'm trying to accomplish a variable phase delay from trigger to action without impacting the ability to read the interrupts.
The Arduino millis() and micros() functions return 32-bit unsigned values for ms or us (to the nearest 4 us) since startup/last-rollover.
The unsigned values and math mean that end time minus start time will always give the time elapsed up to the maximum over 4 billion ms or us that 32-bits can count, -1. With millis timing that's 49.7-some days. With micros timing it's a bit over 70 minutes, IIRC.
You can save a start time, know the desired interval and check if the interval is over with
// repeat the timer, like for blinking a led
if ( millis() - start >= interval ) // if true, the interval has passed
{
// do the timed thing
start += interval; // if you want to repeat the delay on time even if the time check was a bit late
}
// one-shot timer. it takes other code to start this
if ( interval > 0 )
{
if ( millis() - start >= interval ) // if true, the interval has passed
{
// do the timed thing
interval = 0; // some other code has to set interval > 0 to get the one-shot to run
}
}
This needs no interrupts and can run many-many of these soft-timers consecutively as long as they all have their own start times.
Thanks for the help thus far. The millis() suggestion is a good one, I was just starting to investigate that path.
The physical system is a conveyor carrying objects that I need to take photos of for quality control. A first sensor identifies potential defects and generates a digital output, which I will read into the Arduino via interrupts. The conveyor speed may vary (which I will account for separately). Since the camera is farther downstream than the sensor, multiple defective objects may be on the conveyor prior to the camera being activated for the first object. This is leading me towards establishing a timestamp for each event, which I've implemented using a sub-routine each time the interrupt is driven low.
The part I haven't figured out yet is how to timestamp the subsequent objects without impacting the timestamp of the first object.
Do you have a separate sensor to tell you when an object is actually in front of the camera? And will the same Arduino take the picture as identified the defect?
I really don't understand the reason and use of a "time stamp" when a sequential count of the objects would work so much easier.
Unfortunately there's not a separate camera at the sensor. The same Arduino that reads the first sensor will generate the trigger for the camera. Since the conveyor speed is variable, I think it becomes necessary to timestamp each event.
I'll look into arrays, this sounds like it might be the fix.
wonder1001:
Unfortunately there's not a separate camera at the sensor. The same Arduino that reads the first sensor will generate the trigger for the camera. Since the conveyor speed is variable, I think it becomes necessary to timestamp each event.
I'll look into arrays, this sounds like it might be the fix.
I don't think so, at all," I think it becomes necessary to timestamp each event.".
All you need is a sensor to tell the Arduino an object is in front of the camera position. Count the objects passing the camera position. If the camera object number matches one in your list that needs a picture, take the picture.
If the camera object number does not match any needing a picture, don't take it.
Keep a list of object numbers needing a picture. Should not need many if the camera is near the first sensor. Then each time you take a picture eliminate that count from the list.
Can you mark the belt with numbers, letters or bar code or just a registration mark every so far and have objects placed one per marked section? You can then associate object to belt section. You might want marks readable by humans and others readable by machine.
To read bars on a moving belt would take some basic DIY level hardware and code, nothing fancy.
Timing could get a bit complicated if the speed varies unpredictably.
I do have the advantage of knowing the belt speed and plan to compensate the delay using this parameter. Below is a first attempt at using arrays to log the time for each object and respond for each event. Let me know your thoughts.
const byte interruptPin = 2;
int waitTime;
int waitPin = A0;
unsigned long objTime[30];
unsigned long objCount = 0;
int loopIndex = 1;
void setup() {
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), camFlag, FALLING);
}
void loop() {
waitTime = analogRead(waitPin); // Read potentiometer to set wait delay before sending trigger command
//TBD // Add mapping code here to map voltage to time. This will vary based upon belt speed.
if (objCount == loopIndex)
{ // perform action
if ( millis() - objTime[loopIndex] >= waitTime) //
{
camcycle();
loopIndex = loopIndex + 1;
}
else
{
}
}
else
{ // skip action
}
}
void camFlag(){
if(objCount > 29)
{
objCount = 1; // Reset buffer if objCount exceeds 29 objects
loopIndex =1;
}
else
{
objCount = objCount + 1;
}
objTime[objCount] == millis(); //store time of event in array per each object
}
void camcycle(){ //action to take when interval trigger met
// TBD: insert code here to generate trigger pulse
}
Agreed. I haven't advanced it to that level yet, but will likely need to and haven't quite parsed out how that would work yet. For the first go, I'm trying to get it up and running at steady state speed and then focus on how to handle speed transitions. If you have any ideas, I'm all ears.
wonder1001:
For the first go, I'm trying to get it up and running at steady state speed and then focus on how to handle speed transitions. If you have any ideas, I'm all ears.
This is commonly done with an incremental encoder but could be as basic as sensing a piece of reflective tape on the end of a shaft with a photoelectric.