Not nescessary in the microcontroller named propeller-chip.
The "operating system" is the first of 8 cores in combination with a round-robin shared RAM.
The first core starts the task of another one core of the 7 other cores and that's it. Each other core can start additional cores too.
@paulpaulson I think the propeller-chip would be an intellectual challenge for you:
No interrupts still everything is interfaceable even MHz-fast inputsignals,
self-modifying code,
each assembler-instruction can be made conditional on any combination of two flags
Depends on the real details of your project.
You could have an even tinyier 6 IO-pin ultra-mini-microcontroller like an attiny85 controlling
128 io-pins through using 8 16bit IO-expanders blinking and dimming 128 LEDs in parallel to running a stepper-motor.
So if you would give an overview about your project and describe what functionality you want much better suited suggestions can be made.
loop() is confusingly named. It isn't really a loop, it is just a function that is called from the hidden behind-the-scenes for(;;){..} loop in main():
If you call the "loop()s" "functions", then the question might be:
"How do you run multiple functions at the same time?"
And the answer is to rewrite the functions so they can share the processor with each other.
If you have carefully maintained the documentation of your project as to the source and destination of every wire, then soldering/unsoldering is a part of project work in the interest of achieving your objectives.
2.
I can try to design a simple porotype software for you where data exchange with Bluetooth and Car will happen independently if you provide me the following information:
(1) Which device and what message the device will send to your phone via Bluetooth?
(2) How many motors are engaged with your little car? What types of motors they are - stepper, servo or DC? Can you please, post a picture.
(3) How many ultrasonic sensors you have in your project. Please, post a picture of the same.
Not sure if this is a reply to the propeller-chip-posting.
There is no task-scheduling in the propeller-chip as each core (called "COG") runs on the same clock of 80 MHz and runs his own code. This and not having interrupts makes the code-execution extremely deterministic if you want to.
The shared RAM is accessed in a round-robin-manner. As the RAM is shared there is no extra-time needed for exchanging data. Because each COG read/write uses the same variable = the same RAM-adress. The read/write-access is mutually exclusive through the round-robin and has 32bit.
Of course for more than 32 bits some kind of semaphore-managing must be added.
This applies to the programming-language SPIN. Which is a interpreter-language.
There is also a C-compiler for the propeller-chip but I have no knowledge about how it is inside C
void nonBlockingThing1(void) {
static int state = 1;
static unsigned long interval = 0;
static unsigned long last = 0;
unsigned long now = millis(); // if you have a global 'now', use that
if (now - last < interval) return;
last = now;
switch (state) {
case 1:
Serial.print("\nA");
interval = 1000;
state = 2;
break;
case 2:
Serial.print('B');
interval = 1500;
state = 3;
break;
case 3:
Serial.print('C');
interval = 500;
state = 4;
break;
case 4:
Serial.print('D');
Serial.println();
state = 1;
interval = 1000;
break;
}
}
Seriously, coding for a multi-tasking operating system is vastly more complex than "Arduino Style" multi-tasking. You couldn't even handle a water gun without getting your self all wet. With a multi-tasking OS you'll be handed a loaded handgun. The outcome is easily predictable.
It's nothing but my relentless habit to don't do this:
if (millis() - last >= interval) {
last = millis();
It may not matter here, not gonna try to prove to you it ever would, but I like to take one look at the clock (millis()), and use that value everywhere else in code that is supposed to be running at the same time.
I like to have one place where I could change the clock, say to micros() or to myMillis(), which might afford me an opportunity to do all kindsa tricks that would otherwise mean changing all those calls and so forth.
Perhaps you ignored the comment on the line that calls miils()
// if you have a global 'now', use that
I set now at the top of the loop() function. People like to dress it up as currentMillis. Whatever.
I often end up with code that only has one call to millis() and no calls to delay() outside of the setup() function.
I often search code that isn't mine to find delay() and millis(). It gives a quick report on the kind of things I might be dealing with when I read it.
I debated making only the one change that is most least trivial, that is the inversion of the test to reduce the indentation of the real working code in the function.
Word. Until I started using wokwi, I often got most of the logic of a program fairly well along, hardware addressed through functions that just printf()ed that they'd been called and what they would eventually do for realz using regular C/C++ through the CLI or later with an online compiler like tutorialspoint or onlinegdb.