Multiple Timers Arduino - c

Hi I had a question about timers on that Arduino.
I have 5 physical buttons (piezos) that I am getting the analog input from. I am then having them write out a keyboard key. My issue is when one is hit I want it to be unable to hit for "x" amount of time. I tried using delay, but this ended up delaying the whole program, thus 2 buttons could not be hit at the same time. Could someone explain to me how to do this with timers? I want 5 separate timers 1 for each button that controls a Boolean, I would need 5 separate timers for 5 separate if statements. (See code).
//SNARE LOOP2
if(sensorValueA0 == 0)
{
if(SnareHit == false)
{
Keyboard.write(115);
SnareHit = true;
//Use timer here to delay this part of the system
SnareHit = false;
}
}
//BASS DRUM LOOP
if(sensorValueA1 == 0)
{
if(BassHit == false)
{
Keyboard.write(98);
BassHit = true;
//Use timer here to delay this part of the system
BassHit = false;
}
}
Thanks.

You can use the millis() function, something similar to the following code:
if(ButtonPress==true){
time=millis() //time was previously declared as unsigned long
if(time>=5000){ //5000 = 5 sec
ButtonPress==false
}
}
It will not stop the arduino loop as dealy() does.
More info: http://playground.arduino.cc/Code/AvoidDelay

Perhaps you are trying to de-bounce the button. I usually do this in the main loop, and expect 5 consecutive "pressed" reads before I say the button is really pressed, something like this:
int button1PressedCount = 0;
int debounceCounter = 5; // Number of successive reads before we say the switch is pressed
boolean buttonPressed = false;
int inputPin1 = 7;
void setup() {
// Grounding the input pin causes it to actuate
pinMode(inputPin1, INPUT ); // set the input pin 1
digitalWrite(inputPin1, HIGH); // set pin 1 as a pull up resistor.
}
void loop()
{
// Some code
// Check button, we evaluate below
checkButton();
// Some more code
}
void checkButton() {
if (digitalRead(inputPin) == 0) {
// We need consecutive pressed counts to treat this is pressed
if (button1PressedCount < debounceCounter) {
button1PressedCount += 1;
// If we reach the debounce point, mark the start time
if (button1PressedCount == debounceCounter) {
// Button is detected as pressed!
buttonPressed = true;
}
}
} else {
if (button1PressedCount == debounceCounter) {
// We were pressed, but are not any more
buttonPressed = false;
}
button1PressedCount = 0;
}
}
Also it seems using an analogue input with a check if the analogue value is exactly equal to 0 might be a bit sensitive in noisy environments. This is why I use a digital input and the internal pull up resistor.

Related

How to force WinForms into ->Show()

The following code fragment uses a WinForms instance with a button to start a countdown and a textbox to follow it. To simulate a calculation process of any duration, a Fibonacci number is calculated within each count. Regardless of how much time the form element has to react, the countdown is not displayed. Only when everything is finished, the result alone is displayed.
Put simply, I wonder where the event handler gets the idea that it has to wait for the whole process to finish. The calculation has nothing to do with the form element. Actually, it would make more sense to get the calculation 'politely' wait for the UI element, if it lacks the time to display the desired intermediate steps and thus pauses for a moment. Is there any other methode than ->Show() to force a Form window refresh or is this waiting direction perhaps 'default' and can be optionally reversed?
main.cpp
---
form1.h / form1.cpp
---
// sub.cpp ...
void App1::Form1::button1_Click(System::Object^ sender, System::EventArgs^ e) {
unsigned res,dur=40;
System::String^ s;
Form^ fo = Form::ActiveForm;
for(int i = 10;i >= 0;i--) {
res = fibo(dur); // Loop: dur 5|80 ~ instantan|endless
s = i.ToString();
fo->Controls[1]->Text = s;
if(1) fo->Show(); } /// 0|1 no difference ??
s = res.ToString();
fo->Controls[1]->Text = s; }
unsigned fibo(unsigned n) { // time consuming calculation placeholder
long result = 0;
if (n == 0) return 0;
else if (n < 2) result = 1;
else result = fibo(n - 1) + fibo(n - 2);
return result; }
On my way to this question I found articles dealing with 'backgraoundWorker', hence the Fibonacci numbers. But what if the 100% is not known? This complicity all just to show that the process is still alive seems to me a bit break a fly on the wheel. Isn't that done more simple?

Finite State Machine HW/SW event trigger

I'm trying to write a code in C for the FSM of a Vending Machine.
I'm assuming that the machine has 3 basic buttons -- Insert Coins, Choose Product, OK.
I'm going by the concept of creating a look up table with current state, event trigger, next state. I also have an array of function pointers that executes the corresponding function for each state.
However, I am confused on what needs to be chosen as the event trigger.
This is what I have now:
typedef void (*fsmFuncPtr_t)(void);
fsmFuncPtr_t fsmFuncPtr[] =
{
&Idle_State_Handler,
&Insert_Coins_Handler,
&Choose_Product_Handler,
&Validate_Product_Handler,
&Validate_Coins_Handler,
&Dispense_Product_Handler,
&Return_Change_Handler
}
typedef struct
{
fsmState_e cState;
fsmInput_e input;
fsmState_e nState;
} fsm_t;
fsmState_e currentState = IDLE_STATE;
fsmEvent_e currentEvent = No_Input;
fsm_t fsm[] =
{
// cState event nState
{IDLE_STATE, No_Input_Event, IDLE_STATE},
{IDLE_STATE, Insert_Coins_Event, COIN_INSERTION_STATE},
{COIN_INSERTION_STATE, No_Input_Event, COIN_INSERTION_STATE},
{COIN_INSERTION_STATE, Choose_Product_Event, PRODUCT_CHOOSING_STATE},
{PRODUCT_CHOOSING_STATE, OK_Product, VALIDATE_PRODUCT_STATE},
{VALIDATE_PRODUCT_STATE, Product_Valid_Event, VALIDATE_COINS_STATE},
{VALIDATE_PRODUCT_STATE, Product_Invalid_Event, VALIDATE_PRODUCT_STATE},
{VALIDATE_COINS_STATE, Sufficient_Coins_Event, DISPENSE_PRODUCT_STATE},
{VALIDATE_COINS_STATE, Insufficient_Coins_Event, COIN_INSERTION_STATE},
{DISPENSE_PRODUCT_STATE, Balance_Available_Event, RETURN_CHANGE_STATE},
{DISPENSE_PRODUCT_STATE, Balance_Unavailable_Event,IDLE_STATE},
{RETURN_CHANGE_STATE, Change_Returned_Event, IDLE_STATE},
};
void main()
{
while(1)
{
int i = 0;
int fsmTableSize = sizeof(fsm)/sizeof(fsm[0]);
for(i=0; i < fsmTableSize; i++)
{
// intend to get HW triggers here?
if((currentState == fsm[i].cState) && (currentEvent == fsm[i].event) && (fsm[i].fsmFuncPtr != NULL))
{
fsm[i].fsmFuncPtr();
}
}
}
}
So here, No_Input_Event, Insert_Coins_Event, Choose_Product_Event and Ok_Product_Event are events that are triggered by HW. However, all the validation events are events that would be triggered by SW/FW based on the current values of product code and available number of coins. So I'm confused where I should be obtaining/manipulating these events.
Or should I only have the HW triggers as triggers and just make silent state transitions based on validation results ?

How to create array of object instances in vala

as I was trying to nail down the bug why my gtk4_list_clocks only ever update one of the clocks and not all of them, I've traced down the problem to be in GLib.SList.prepend().
Changing from GLib.SList to Gee.ArrayList didn't solve the problem.
In the c code example a list of all clock widgets were created by appending them to a singly linked list. I've tried to mimic that but as it turned out the list size is always 1 and only one object ever get appended.
/* This is the list of all the ticking clocks */
static Gee.ArrayList<Clock> ticking_clocks = null;
// ...
construct {
ticking_clocks = new Gee.ArrayList<Clock> ();
}
void start_ticking () {
/* if no clock is ticking yet, start */
if (ticking_clock_id == 0) {
ticking_clock_id = GLib.Timeout.add_seconds (1, tick);
}
ticking_clocks.add (this); // Bug
// Although instance pointer is different according to the number of instantiated objects!!!
print ("Clock instance %p\n", this);
// always 1 !!!
print ("Number of ticking clocks %d\n", ticking_clocks.size);
}
Could somebody please help to point out the problem?
Thanks in advance.
This works:
void main () {
var a = new SList<Clock> ();
a.append (new Clock ());
a.append (new Clock ());
a.append (new Clock ());
a.append (new Clock ());
a.append (new Clock ());
print (#"Array length is $(a.length())\n");
}
class Clock {}
I'm not sure what the problem would be in your code, but I would remove the static from the ticking_clocks field. It can also be initialised with:
private Gee.ArrayList<Clock> ticking_clocks = new Gee.ArrayList<Clock> ();
I would also move the ticker outside the instance. If your SourceFunc returns Source.CONTINUE it will carry on ticking. Here is a stripped back example using MainContext. MainContext is the event loop within GLib's MainLoop, GApplication, etc. It is useful to understand to get a good grasp of Vala's async functions/methods:
void main () {
var maincontext = MainContext.default();
var time_to_quit = false;
var count = 5;
SourceFunc quit = () => {
print (#"$count\n");
count --;
var result = Source.CONTINUE;
if (count < 1) {
time_to_quit = true;
result = Source.REMOVE;
}
return result;
};
Timeout.add_seconds (1, (owned)quit);
while (time_to_quit == false) {
maincontext.iteration( true );
}
}
Be aware the Timeout is not precise, it is at least a second. So you may want to increase the frequency and then check the time when you update the clock.

Synchronizing different messages

I think it's a general software paradigm problem, so it's not related that much to embedded software.
I have 3 Messages that I get at different time slices, the three messages are
Odo, velocity, gps. each one has timeslice 20ms, 1sec, and 1sec.
My problem is how would I sync and get a complete message only when the three are already fetched.
My current approach is to have three circural queues, and put three boolean variables and check if they are all in sync, but that doesn't work if for example odo which has timeslice 20ms, is pulled over and over without the other messages.
Here is what I'm doing:
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxMessage, RxData);
static bool t1 = 0, t2=0, t3 =0;
if (RxMessage.StdId == 0x098)
{
insertCirQueue(&q_velocity, 0x098);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
t1=1;
}
else if (RxMessage.StdId == 0x309)
{
/* Rx message Error */
insertCirQueue(&q_Odo, 0x309);
t2=1;
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13);
}
else if (RxMessage.StdId == 0x3EB)
{
/* Rx message Error */
insertCirQueue(&q_Gps, 0x3EB);
t3=1;
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14);
}
if (t1 && t2 && t3)
{
t2 = t3 = t1 = 0;
isSynced = true;
}
}
and in the main loop
if (isSynced)
{
isSynced = false;
int vel[8] = {0}, gps[8] = {0}, odo[8] = {0};
int counter = 0;
while (!isEmpty(&q_velocity))
{
if (deleteCirQueue(&q_velocity, &vel[counter++]) == -1)
break;
}
counter = 0;
while (!isEmpty(&q_Gps))
{
if(deleteCirQueue(&q_Gps, &gps[counter++]) == -1)
break;
}
counter = 0;
while (!isEmpty(&q_Odo))
{
if(deleteCirQueue(&q_Odo, &odo[counter++]) == -1)
break;
}
You create a bit-field, and set a bit per received message type.
typedef enum
{
RECEIVED_NONE = 0x00,
RECEIVED_ODO = 0x01,
RECEIVED_VELO = 0x02,
RECEIVED_GPS = 0x04,
RECEIVED_ALL = RECEIVED_ODO | RECEIVED_VELO | RECEIVED_GPS,
} can_received_t;
can_received_t can_received = RECEIVED_NONE;
if(/* received odo */)
{
can_received |= RECEIVED_ODO;
}
...
if(can_received == RECEIVED_ALL)
{
can_received = RECEIVED_NONE;
...
}
Storing queues seem fishy though. The normal procedure for CAN, being a real-time bus, is that you only keep the latest valid package and discard the rest. Particularly when dealing with sensors and control functions.
You could just use the last value received every time. So you could receive a bunch of updates for the odometer, but only "latch" it in when the last of gps/velocity have been collected (pick one to sync to). If you're getting them from a system that periodically and predictably sends you messages, that's easy. You don't even need a queue, except for finalized values (if you want to see/use trending history).
If you care about being synchronized and accurate, you could interpolate your velocity. Do the same thing as above for the odometer, and stop saving it once the GPS is collected. Collect 2 values for velocity (before the GPS collection, and after). Interpolate the velocity (linearly) to generate the velocity value at the GPS collection time. Then report that out. This will generate a synchronized and accurate value every time the velocity is collected, delayed by the offset between your velocity/GPS collection timestamps.

Display response time seems too slow on simple functions

I have written an application in C using GTK 2.0 for a touchscreen panel with an ARM processor running debian linux. It is a very basic application that presents a few buttons (event boxes) on screen that can be clicked. On one page, I have 4 fields to present a "list" that can be scrolled through by clicking an up arrow and a down arrow (also event boxes). My function (code below) for the scrolling is very basic...it just updates each field with the next item from the array. Everything works fine, but the problem I am seeing is that if you repeatedly click the scroll button a little too quickly, it jumps ahead a few list items too far. My guess as to what is happening is that, when clicking too fast, the counter advances faster than the screen can update, so that by the time you click again it is actually updating with the then too-high counter. I wouldn't be concerned if it only happened when clicking REALLY fast, but I think the slow response seems way out of line for such a simple function repeating at a reasonably quick rate.
I'm hoping maybe someone has some input on something I might be missing in regards to screen refreshes with GTK?
Thank you in advance for any thoughts or advice!
Here is my code for my "volume-up" function and "scroll-up" function, both having the same problem. There are corresponding "scroll-down" and "volume-down" functions with the same issue:
static void sr_vol_up_clicked (GtkWidget *fakewidget, GdkEvent *fakeevent, gpointer number)
{
g_timer_start(lock_timer);
gtk_image_set_from_file (GTK_IMAGE(sr_vol_up_button),"./images/Admin/navigation_up_arrow_DOWN.png");
if (sr_current_level < 100)
{
sr_current_level = sr_current_level + 1;
gtk_label_set_text (GTK_LABEL(sr_current_level_label), (g_strdup_printf("%i", sr_current_level)));
set_sr_volume(sr_current_level);
}
gtk_image_set_from_file (GTK_IMAGE(sr_vol_up_button),"./images/Admin/navigation_up_arrow_UP.png");
}
And the other:
static void scroll_show_up ()
{
g_timer_start(lock_timer);
if (show_scroll_count > 0)
{
if (show_one_displayed - 1 < 0)
{
show_one_displayed = (show_loop_list->len -1);
}
else
{
show_one_displayed = show_one_displayed - 1;
}
gtk_label_set_text (GTK_LABEL(upcoming_show_1_label), get_show_name((char *)g_ptr_array_index(show_loop_list, show_one_displayed)));
if (show_two_displayed - 1 < 0)
{
show_two_displayed = (show_loop_list->len -1);
}
else
{
show_two_displayed = show_two_displayed - 1;
}
gtk_label_set_text (GTK_LABEL(upcoming_show_2_label), get_show_name((char *)g_ptr_array_index(show_loop_list, show_two_displayed)));
if (show_three_displayed - 1 < 0)
{
show_three_displayed = (show_loop_list->len -1);
}
else
{
show_three_displayed = show_three_displayed - 1;
}
gtk_label_set_text (GTK_LABEL(upcoming_show_3_label), get_show_name((char *)g_ptr_array_index(show_loop_list, show_three_displayed)));
if (show_four_displayed - 1 < 0)
{
show_four_displayed = (show_loop_list->len -1);
}
else
{
show_four_displayed = show_four_displayed - 1;
}
gtk_label_set_text (GTK_LABEL(upcoming_show_4_label), get_show_name((char *)g_ptr_array_index(show_loop_list, show_four_displayed)));
show_scroll_count = show_scroll_count - 1;
}
}

Resources