Controlling car with button and voice via Bluetooth

Hi.
I want to control my car with button and voice via Bluetooth. I tried to create 2 task: VoiceControl and ButtonControl but they didn’t work as I expected. After discussion on this forum, I decided to post my flow chart of the origin code. Looks like I missed some solutions.
Hope you can help me. Thank you all.

For completeness reasons

is the previous discussion Lucy is referring to.

Hi @Lucy781227

I’m not sure what distinguishes this issue from the original post. If it’s all the same issue, please keep a single thread so everything is there, should anyone have similar queries in the future.

From what I last got from the original thread, you can simply make a queue for the voice commands, and have the listener task continuously listen. Whatever tasks acts on those commands, every 2 seconds IIRC, can simply pop from that queue independent of whether the listening task is currently in-taking another command.

Yes, it is. I dont know what I missed. :frowning:

I see. But there’s a problem here. When VoiceControl is running, I set a delay ~2s for each action. But right after saying a command, if I clicked on the button, I want my car to move following that button.

It was my fault. Thanks for telling me.

What about the hints already given to keep the task responsive to further input events (button or voice) from Bluetooth after the car was started resp. while the car runs ?

When using the ‘hints’, you mean semaphore?

When controlling by voice, if you say ‘go straight’, it means the car will be going straight for 2s and then stop. It’s like

GoStraight();
delay(2000);
Stop();

During 2s, if there is a button signal, I want my car to move following it. But if I used semaphore, when there’s no more button signal, VoiceControl will be resumed with the rest of code. I want it to start from the beginning.

It sounds like you need a somewhat more complicated sequencing system.

Likely a “Voice” system and a “Button” system that issue commands to a “Car” system with a queue.

If you want commands to be able to interrupt other commands, then rather than doing Go / Wait / Stop, the Go needs to start a timer, which issues the Stop command when the timer expires (and if a command interrupts, it cancels the timer).

I didn’t mention semaphore:thinking:
My point was and is that you should build a state machine resp. a sequencing system as also Richard proposed and use a timeout (or a timer) for the delays.
The task could always poll for incoming events and just trigger the desired action, if an event arrived. The states of the state machine reflect the states of the car.
If a timeout (e.g. 2 s) was set (because there was an event to trigger GoStraight), check for the expiration of the armed timeout while still polling for incoming events (to issue Stop on expiration) or re-start the timeout if another GoStraight event comes in…
Good luck :+1:

Yes. I create functions for them, just using analogWrite(HIGH) or LOW.

I see. So setting a timer is different with delay() or vTaskDelay()?

You really should get more familiar also with FreeRTOS. This will help you a lot !
There is a very good documentation for instance here: