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.
Related
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 ?
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.
I am trying to migrate a custom dynamic partitioner from Flink 1.7 to Flink 1.9. The original partitioner implemented the selectChannels method within the StreamPartitioner interface like this:
// Original: working for Flink 1.7
//#Override
public int[] selectChannels(SerializationDelegate<StreamRecord<T>> streamRecordSerializationDelegate,
int numberOfOutputChannels) {
T value = streamRecordSerializationDelegate.getInstance().getValue();
if (value.f0.isBroadCastPartitioning()) {
// send to all channels
int[] channels = new int[numberOfOutputChannels];
for (int i = 0; i < numberOfOutputChannels; ++i) {
channels[i] = i;
}
return channels;
} else if (value.f0.getPartitionKey() == -1) {
// random partition
returnChannels[0] = random.nextInt(numberOfOutputChannels);
} else {
returnChannels[0] = partitioner.partition(value.f0.getPartitionKey(), numberOfOutputChannels);
}
return returnChannels;
}
I am not sure how to migrate this to Flink 1.9, since the StreamPartitioner interface has changed as illustrated below:
// New: required by Flink 1.9
#Override
public int selectChannel(SerializationDelegate<StreamRecord<T>> streamRecordSerializationDelegate) {
T value = streamRecordSerializationDelegate.getInstance().getValue();
if (value.f0.isBroadCastPartitioning()) {
/*
It is illegal to call this method for broadcast channel selectors and this method can remain not
implemented in that case (for example by throwing UnsupportedOperationException).
*/
} else if (value.f0.getPartitionKey() == -1) {
// random partition
returnChannels[0] = random.nextInt(numberOfChannels);
} else {
returnChannels[0] = partitioner.partition(value.f0.getPartitionKey(), numberOfChannels);
}
//return returnChannels;
return returnChannels[0];
}
Note that selectChannels has been replaced with selectChannel. So, it is no longer possible to return multiple output channels as originally done above for the case of broadcasted elements. As a matter of fact, selectChannel should not be invoked for this particular case. Any thoughts on how to tackle this?
With Flink 1.9, you cannot dynamically broadcast to all channels anymore. Your StreamPartitioner has to statically specify if it's a broadcast with isBroadcast. Then, selectChannel is never invoked.
Do you have a specific use case, where you'd need to dynamically switch?
So I have the following script to get all combination of an array :
'''
var value = new Array(40)
for (var i=0;i<value.length;i++){
value[i]=i;
}
var comb_list = getAllComb(value,24);
trace(comb_list)
function getAllComb(values:Array, r:int):Array{
var n = values.length;
var result = new Array();
var a = new Array(r);
// initialize first combination
for (var i = 0; i < r; i++) {
a[i] = i;
}
i = r - 1; // Index to keep track of maximum unsaturated element in array
// a[0] can only be n-r+1 exactly once - our termination condition!
var count = 0;
while (a[0] < n - r + 1) {
// If outer elements are saturated, keep decrementing i till you find unsaturated element
while (i > 0 && a[i] == n - r + i) {
i--;
}
result.push(a.slice())// pseudo-code to print array as space separated numbers
count++;
a[i]++;
// Reset each outer element to prev element + 1
while (i < r - 1) {
a[i + 1] = a[i] + 1;
i++;
}
}
return result;
}
'''
Running above script will get me:
Error: Error #1502: A script has executed for longer than the default timeout period of 15 seconds.
How to add time delay each 14 seconds passed so that I can run the script? So, after 14 seconds passed, the program will wait for 50ms then continue.
Any help appreciated.
So, there's a simple (well, pretty much so) and working example of how to separate the heavy calculations part from the main thread so the main thread (which also handles UI and external events like user input) would run smoothly, while being able to read the progress and the results of the heavy calculations going under the hood. It also is in a form of a single class, this could be a bit confusing (until you understand how it works) but still easy to handle and modify.
Although the background AVM goes along the same execution flow (code execution > graphics rendering > code execution > graphics rendering > and so on), there are no graphics to render hence there's no need to anyhow limit the code execution time. As a result Worker thread is not a subject to 15 seconds limit, which, somehow, solves the problem.
package
{
import flash.events.Event;
import flash.display.Sprite;
import flash.utils.ByteArray;
import flash.concurrent.Mutex;
import flash.system.Worker;
import flash.system.WorkerDomain;
public class MultiThreading extends Sprite
{
// These variables are needed by both the main and
// subservient threads and will actually point to
// the very same object instances, though from
// the different sides of this application.
private var B:ByteArray;
private var W:Worker;
private var M:Mutex;
// Constructor method.
public function MultiThreading()
{
super();
// This property is 'true' for the main thread
// and 'false' for any Worker instance created.
if (Worker.current.isPrimordial)
{
prepareProgress();
prepareThread();
startMain();
}
else
{
startWorker();
}
}
// *** THE MAIN THREAD *** //
private var P:Sprite;
private var F:Sprite;
// Prepares the progress bar graphics.
private function prepareProgress():void
{
F = new Sprite;
P = new Sprite;
P.graphics.beginFill(0x0000FF);
P.graphics.drawRect(0, 0, 100, 10);
P.graphics.endFill();
P.scaleX = 0;
F.graphics.lineStyle(0, 0x000000);
F.graphics.drawRect(0, 0, 100, 10);
F.x = 10;
F.y = 10;
P.x = 10;
P.y = 10;
addChild(P);
addChild(F);
}
// Prepares the subservient thread and shares
// the ByteArray (the way to pass messages)
// and the Mutex (the way to access the shared
// resources in a multi-thread environment
// without stepping on each others' toes).
private function prepareThread():void
{
M = new Mutex;
B = new ByteArray;
B.shareable = true;
B.writeObject(incomingMessage);
W = WorkerDomain.current.createWorker(loaderInfo.bytes);
W.setSharedProperty("message", B);
W.setSharedProperty("lock", M);
}
// Starts listening to what the background thread has to say
// and also starts the background thread itself.
private function startMain():void
{
addEventListener(Event.ENTER_FRAME, onFrame);
W.start();
}
private var incomingMessage:Object = {ready:0, total:100};
private function onFrame(e:Event):void
{
// This method runs only 20-25 times a second.
// We need to set a lock on the Mutex in order
// to read the shared data without any risks
// of colliding with the thread writing the
// same data at the same moment of time.
M.lock();
B.position = 0;
incomingMessage = B.readObject();
M.unlock();
// Display the current data.
P.scaleX = incomingMessage.ready / incomingMessage.total;
P.alpha = 1 - 0.5 * P.scaleX;
// Kill the thread if it signalled it is done calculating.
if (incomingMessage.terminate)
{
removeEventListener(Event.ENTER_FRAME, onFrame);
W.terminate();
B.clear();
B = null;
M = null;
W = null;
}
}
// *** THE BACKGROUND WORKER PART *** //
// I will use the same W, M and B variables to refer
// the same Worker, Mutex and ByteArray respectively,
// but you must keep in mind that this part of the code
// runs on a different virtual machine, so it is the
// different class instance thus its fields are not
// the same quite as well.
// Initialization.
private function startWorker():void
{
W = Worker.current;
M = W.getSharedProperty("lock");
B = W.getSharedProperty("message");
// Before starting the heavy calculations loop
// we need to release the main thread which is
// presently on W.start() instruction. I tried
// without it and it gives a huuuge lag before
// actually proceeding to intended work.
addEventListener(Event.ENTER_FRAME, onWorking);
}
private function onWorking(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, onWorking);
var aMax:int = 10000000;
// Very very long loop which might run
// over the course of several seconds.
for (var i:int = 0; i < aMax; i++)
{
// This subservient thread does not actually need to
// write its status every single loop, so lets don't
// explicitly lock the shared resources for they
// might be in use by the main thread.
if (M.tryLock())
{
B.position = 0;
B.writeObject({ready:i, total:aMax});
M.unlock();
}
}
// Let's notify the main thread that
// the calculations are finally done.
M.lock();
B.position = 0;
B.writeObject({ready:i, total:aMax, terminate:true});
M.unlock();
// Release the used variables and prepare to be terminated.
M = null;
B = null;
W = null;
}
}
}
The error is not related to your script needing a time delay, the problem is your while loops are making your script unresponsive for more than 15 seconds, triggering the script timeout error. Action Script only allows 15 seconds for your script to execute.
Your first while loop looks problematic, and I'm unclear how the value of a[0] changes to end the loop. Add a break to the loop or make sure the condition changes to allow the loop to end, and you should solve your problem. You can also considering adding continue statements to your embedded while loops if they are only supposed to run one time after they find an unsaturated value.
Personally, since you are using ActionScript, I'd suggest using objects and listeners for value changes instead of iterating over arrays checking for changes.
You could also add a manual timeout for your while loop, but would need to include logic for it to pick up where it left off.
//Set timer to 14 seconds
timeout = getTimer() + 14000;
while(true && timeout > getTimer()){
trace("No Error");
}
If you were used Adobe Animate (Flash), you could change the "Script Time Limit" from Publish setting page.
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.