Well, the endless rabbitholing seems determined to persist. The Waveshare ESP32S3 boards I got from Amazon seem to indeed "share" a lot in common with their ESP32 siblings. Namely I struggle to get them to behave at all. Even when following the manufacturer's instructions to the tee, I can't get the fuckers the work. And no, it's not just that The Stupid Fat Block doesn't know what he's doing - that surely can't be helping - but on the myriad forums, users of all capabilities and none are sharing the same frustration. I've got a life to live, so the ESP32 family can shove it.
So I'm going to fall back on the "proven" solutions ie "official Arduino boards made and sold by Arduino" (through Amazon) using microcontrollers of know parentage.
What happened to the ESP32S3, then?
Well, firstly the S3 and C3 boards are "more different" than I'd expected. For one thing, the S3 has more pins and for another, the board layout is completely different, as in the pins are on opposite sides of the board. TBH, all I was hoping for was a dual core board in the same form / footprint / pinout, so that the stepper speed control could run independently to the pulsing function. But then I completely failed to even get it to talk to me. I seemed to have bricked the damned thing. Probably not bricked , technically speaking, but either way it was no use to man nor beast - and certainly not to The Stupid Fat Bloke.
So, to start with, I'm gong to immediately break the "official Arduino boards made and sold by Arduino" notion by instead using a Waveshare RP2040 Zero "mini" board using an RP2040. What???
Let's get this Waveshare RP2040 Zero running, then:
The whole point of this dual core shenanigan is to run the motor speed control in one core and the pulsing control in another, with minimal impact of one on the other. Can we finally, finally get there?
The setup for the Waveshare board appears to be pretty much the same as that required for the Arduino Pico The installation of the RP2040 into the board manager needs to be done first and seems to also download some relevant RP2040 examples.
Once you've got the board set up as a "Waveshare RP2040 Zero" in the Arduino IDE board manager, it's time to try out multi core processing. This code seems to work:
// Core0 setupvoid setup(){Serial.begin(115200);}void loop(){Serial.printf("Core 0-1...\n");}// Core1 setupvoid setup1(){Serial.printf("Core 1-1...\n");}void loop1(){Serial.printf("Core 1-2...\n");}
This does almost nothing but at least it compiles and works. It's basically setup(), loop(), setup1(), loop1(), with relevant content for core0 and core1 within each segment. Pretty simple on the face of it.
- graft the pulsing software into one of the cores and convince myself it works.
- graft the stepper speed control onto one of the cores etc etc
- try to get both functions to coexist.
One issue with the Zero is that the RGB onboard LED isn't just a simple LED, so it's not possible to just turn it on. No problem - I'll rely on the serial monitor, although it's a bit of an annoyance.
Let's get the pin allocations decided. Here's the Zero's layout:
Looks as if I can use A0...A2 for the analogue inputs and D29 for the step output, keeping the external connections grouped together for no obviously compelling reason.
This works:
#include <AccelStepper.h>// constants to set pin numbers = 13 - use built in LED for test / devconst int pwmPin = 13; // the number of the green LED pinconst int dutyCycleAnalogIn = A0; // Analog input- PWM dutyconst int periodAnalogIn = A1; // Analog input - period (ms)const int speedAnalogIn = A2; // Analog input - speed (Hz)const int maxPeriod = 5000; // hard coded max on timeconst int dirPin = 5; // pin 5 used for DIR outputconst int stepPin = 4; // pin 4 used for STEP output// Variables will changeint pwmState = HIGH; //ledState for PWM outputint pwmSensorValue = 0; // value read from the potint periodSensorValue = 0;int speedValue = 0;long plot = 0;AccelStepper stepper1(AccelStepper::DRIVER, stepPin, dirPin); // (Type of driver: with 2 pins, STEP, DIR)long previousMillisPwm = 0; //last time PWM output was updatedlong previousMillisPeriod = 0;// pwmPeriod is time between spotslong pwmPeriod = 2000; //interval between spots (milliseconds)// must be long to prevent overflowlong pwmDuration = 2000; //interval for PWM output (milliseconds)unsigned long currentMillis = 0; // initialisevoid setup(){// Set maximum speed value for the stepper:stepper1.setMaxSpeed(1000);// set the pins to output modeSerial.begin(9600);pinMode(pwmPin, OUTPUT);digitalWrite(pwmPin, pwmState);currentMillis = millis();}// Core1 setupvoid setup1(){// Serial.printf("Core 1-1...\n");}void loop(){analogRead(0); // could be any channelperiodSensorValue = analogRead(periodAnalogIn); // 0 - 1023 countpwmPeriod = (maxPeriod * periodSensorValue / 1023); // map input to pwmPeriod - time between spotspwmSensorValue = analogRead(dutyCycleAnalogIn); // 0 - 1023 countpwmDuration = map(pwmSensorValue, 0, 1023, 0, pwmPeriod); // map input to pwmDuration - on timecurrentMillis = millis(); // capture the current timemanagePwm();managePeriod();serial_Plotter();reportStatus();}void loop1(){// speedValue = analogRead(speedAnalogIn); // Define setSpeed() according to input A2speedValue = map(analogRead(speedAnalogIn), 0, 4095, 400, 4095); // Define setSpeed() according to input A2stepper1.setSpeed(speedValue); // Step the motor with a constant speed previously set by setSpeed();stepper1.runSpeed();Serial.print("Speed ");Serial.println(speedValue);}void reportStatus(){Serial.print("Duty time is");Serial.print("\t");Serial.print(pwmDuration);Serial.print("\t");Serial.print("Period time is");Serial.print("\t");Serial.print(pwmPeriod);Serial.print("\t");Serial.print("Output");Serial.print("\t");Serial.print(plot);Serial.println("\t");}void serial_Plotter(){if(pwmState == HIGH){plot=1;} else{plot=0;}}void managePwm(){//check if it's time to change the PWM output yetif(currentMillis - previousMillisPwm > pwmDuration){//store the time of this changepwmState = LOW;digitalWrite(pwmPin, pwmState);}}void managePeriod(){//check if it's time to reset the output yetif(currentMillis - previousMillisPeriod > pwmPeriod){previousMillisPeriod = currentMillis;previousMillisPwm = currentMillis;pwmState = HIGH;digitalWrite(pwmPin, pwmState);}}
...but the text outputs from core0 and core1 arrive on top of each other. That's not an issue really.
20:21:07.245 ->20:21:07.245 -> Duty time is Speed 24260420:21:07.245 -> Period time isSpeed 604109420:21:07.245 -> Speed Output60420:21:07.245 -> 0Speed 60420:21:07.245 ->20:21:07.245 -> Duty time isSpeed 60424120:21:07.245 -> Speed Period time is60420:21:07.245 -> 1089Speed 603Output20:21:07.245 -> Speed 060420:21:07.245 ->20:21:07.245 -> Speed 603Duty time is20:21:07.245 -> 241Speed 605Period time is20:21:07.245 -> Speed 108960520:21:07.245 -> OutputSpeed 605020:21:07.245 -> Speed20:21:07.245 -> 60520:21:07.245 -> Duty time isSpeed 60524320:21:07.245 -> Speed Period time is605
etc etc
Next - check the physical inputs and outputs actually function as expected. I seem to be making progress finally....
No comments:
Post a Comment