0

I have an application that runs a stepper motor from an Arduino board. This requires use of the delayMicroseconds(int us) to control the speed at which the motor turns. For this reason, all code within the main loop() must execute extremely quickly or the stepper movement will become choppy or slow.

I am also using the Serial.readString() function to receive instructions on when the stepper should move and the Serial.println(string val) function to send the current position data back to the caller. The serial library is not particularly fast compared to the rest of the program as serial writes will take milliseconds (which is too slow for the stepper).

To solve this another thread could be used to manage the communications portion of the program and leave one thread exclusively for running the stepper motor. This will require that the threads are able to communicate with each other in a way that does not take a long time. Alternatively as the Pro supports MicroPython if there is a way to communicate between the Arduino program and a MicroPython application the python part could handle the serial communications.

The following link is the best example I could find and it does not show any communication between programs. Dual Core Processing

Example Pseudo-code

The following is an example of how I think this could work if the two cores could communicate with each other directly. As I am unsure whether this is possible I am also unsure whether any thread-locking would be required to prevent deadlocks.

Core 1

const int pinPulse = 2;
const int pinDirection = 3;

int moveTo = 0;
int currentLocation = 0;

void loop() {
    if (currentLocation != moveTo) {
        // Set direction
        if (currentLocation > moveTo)
            digitalWrite(pinDirection, HIGH);
        else
            digitalWrite(pinDirection, LOW);

        // Run movement
        executeMovement();

        // Update position
        if (currentLocation > moveTo)
            currentLocation--;
        else
            currentLocation++;
    }
}

void executeMovement() {
    digitalWrite(pinPulse, HIGH);
    delayMicroseconds(250);
    digitalWrite(pinPulse, LOW);
    delayMicroseconds(500);
}

int getCurrentLocation() {
    return currentLocation;
}

void setMoveTo(int val) {
    moveTo = val;
}

Core 2

Thread core1; // Pseudo-code

void loop() {
    // Check for and update new move to location
    while(Serial.available() > 0 ) {
        String input = Serial.readString();
        core1.setMoveTo(input.toInt()); // Assuming input can always be parsed to int
    }

    // Return position to caller
    Serial.println(core1.getCurrentLocation());
}
  • this is a task for ATiny. only use timer to control the motor – Juraj Jul 1 at 17:29
  • @Juraj I'm not sure I follow. Do you mean that I should add a timer in the setup() function and have that signal an ATtiny device? – foochow Jul 1 at 17:52
  • an ATiny can control a motor and read the Serial 'at the same time' if you code it right. the microcontrolers have independent timer peripherals. you don't need a canon to shot rabbits. – Juraj Jul 1 at 18:18
  • 1
    as Juraj said, it seems that the hardware can help you here, in form of hardware timers or PWM libraries. Communication between the M7 and M4 on the Portenta H7 is possible, since there's 64KByte of shared SRAM between the cores. See freertos.org/STM32H7_Dual_Core_AMP_RTOS_demo.html and the datasheets and reference manuals at st.com/en/microcontrollers-microprocessors/…. SRAM4 at 0x38000000 with a size of 64kBytes is seen from both cores in the same state. On the M7 you can e.g. handle serial and write to the shared SRAM and read it on the M4. – Maximilian Gerhardt Jul 1 at 18:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.