Finite State Machine HW/SW event trigger - c

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 ?

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?

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.

How to make what function I use in c be controlled by a variable

This is my first year of vex. I am taking on the role of programmer.
I have had this idea for rapid autonomous creation, recording the driver. Instead of the usual array/debugger dump of raw streams of power levels, I had the idea of extracting functions from driver movement.
I wont go into the details, and I can code it myself, but I need some help.
There is one thing I am unable to do simply because of my lack of coding experience.
I want to create a for loop that checks every joystick button one by one.
For example:
struct button
{
bool pressed;
}
for(int i = 0; i>12; i++) //12 is number of buttons on the joystick
{
struct button button<cycle through buttons>;
}
I want there to then be:
struct button button6U;
struct button button6D;
struct button button6R;
etc.
Then, I want this:
for(int i = 0; i>12; i++) // 12 is number of buttons on the joystick
{
if(VexRT[<currentButton>])
{
button<currentButton>.pressed = true;
}
}
I have no idea how to do this, with a wildcard modifing the actual variable name I am writing to.
A couple thoughts:
A for statement would have no idea how to advance the order of joystick buttons. So something I think I might need is:
orderOfButtons
{
VexRT[6U];
VexRT[6D];
VexRT[6R];
// etc.
}
I just cant seem to figure out how to have a variable defining what VexRT[]button I am reading from.
Any help would be appreciated!
Thanks.
Sounds like you want an array:
#define NUMBER_OF_BUTTONS 12
...
struct button VexRT[NUMBER_OF_BUTTONS];
If you want to use symbolic constants to refer to specific buttons in the array, you can use an enumeration:
enum btn_id { BTN_6U, // maps to 0
BTN_6D, // maps to 1
BTN_6R, // maps to 2
...
}
Enumeration constants are represented as integers, and by default they start at 0 and increment by 1. You can initialize them to different values if you want, and multiple enumeration constants can map to the same value. I take advantage of this when I want to identify a "first" and "last" enumeration for looping, like so:
enum btn_id {
BTN_6U,
BTN_FIRST = BTN_6U, // both BTN_FIRST and BTN_6U will map to 0
BTN_6D,
BTN_6R,
...
BTN_whatever,
BTN_LAST
};
Thus, VexRT[BTN_6U] maps to VexRT[0], VexRT[BTN_6D] maps to VexRT[1], etc.
Note that this way, you don't have to loop through all the buttons just to set one:
enum btn_id currentButton = BTN_6D;
...
VexRT[currentButton].pressed = true;
If you do want to loop through the whole set, you can use
for ( enum btn_id i = BTN_FIRST; i < BTN_LAST; i++ )
{
VexRT[i].pressed = false;
}
So, what you want is to sample the user input (at some specified rate), then record it into an array, then play that back at a later time? If you have functions that drive the VEX (I'm not familiar with that), each of which are associated with an input, you can use an array of function pointers to create your output.
#define MAX_ACTION 12
#define MAX_RECORDED 200
// Declare your array of function pointers
int (*action[MAX_ACTION])(void);
// Declare your stored array of recorded actions
int recorded[MAX_RECORDED];
...
// Assign function pointers to associated functions
action[0] = go_forward;
action[1] = turn_right;
...
// Record your actions into some array
while (...)
{
// Record the action
recorded[i++] = get_action();
// Sample delay
}
...
// Playback the actions
for (i=0;i<RECORDED;i++)
{
(*action[recorded[i]])();
// delay here
}
P.S. Your for loop is backward (i<12 not i>12).
I think you are trying to access the events coming from the joystick. You can just loop through the array of values and record them. I think the channels on the joystick are simply accessed like: vexRT[x] where x is 1-12. If you just want to store the latest value from each channel you could do this:
int value[12];
for(i=0; i<12; i++)
{
value[i] = vexRT[i];
}
If you want to store all of the values so that you can map them or play them back or something then you will need a more complex data structure to store them, like a list of the value arrays.
I also have found documentation that says the values are accessed by like vexRT[Chx] where x is 1-12, so you could alternatively create a string and use it to access the joystick channels inside your loop:
string *s = (char *)malloc(5*sizeof(char)); //5 is the max length of the null terminated string
for() . . . {
sprintf(s,"Ch%d", i);
value[i] = vertRT[s];
}

Stop angular from updating table

I am using angluar js. On my page I have a table. Each record in the table has a col that is a drop down list. When this value gets changed and the user clicks save, the page checks to see if the value in the drop down has already been used. If it has, an alert message is presented and if not, then some code is executed. My problem is when the alert/error message is displayed. When this is displayed, I don't want the table to update according to the new value but it still does. How can I prevent this? I am really new to using angular.
$scope.saveDeviceUpdate = function (updatedDevice, deviceId) {
var numDevicesForBus = 0;
for (var i = 0; i < $scope.data.deviceList.length; i++)
{
if ($scope.data.deviceList[i].BusNumber == updatedDevice.busNumber)
{
numDevicesForBus++;
}
}
if (numDevicesForBus == 0)
{
dataService.updateDevice(updatedDevice, deviceId);
}
else
{
alert("This bus already has a device!");
}
};

Multiple Timers Arduino

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.

Resources