what is an efficient method for transposing N timing arrays into one master array? - arduino

This is an extremely niche problem, so I'll do my best to explain it in words:
Say you have an operation that requires negligible time (in my case, stepping a stepper motor once by pulsing the pins). I want to coordinate the movement of 6 individual motors with their own acceleration curve, but actuate them with the same micro controller. I also want the individual acceleration curves of the motors to be modifiable.
I'm using a Teensy 4.1, so this program will be written in Arduino language (near identical to C++).
My current approach to this problem is to generate six individual "delay" arrays for each motor. Essentially, their speed is controlled by the delay in between each pulse, and the angular distance traveled by the # of steps, or elements of each delay array. Something like this:
1 (P20) 1 (P20) 1 (P20) 1
2 (P30) 2 (P30) 2 (P30) 2
Where a 1 or 2 is the respective motor's step and a (PX) is a delay for X seconds.
I would like to write some master transposition function that turns the above into this:
1,2 (P20) 1 (P10) 2 (P10) 1,2 (P20) 1 (P10) 2
This array, when read by my actuation code would step motors 1 and 2 at the same time, wait 20 microseconds, step motor 1, 10 microseconds, step motor 2... etc.
It seems pretty simple when you do it for two motors, but for some reason I just can't wrap my head around making a completely modular version of this. In my case, it would need to merge 6 arrays into one.
I am also just wondering if anyone could think of a more elegant solution to this problem, as I am pretty new to programming and don't know all the features / capabilities of C++.
I have tried applying an iterative method, where you keep track of the current total delay elapsed and subtract it from the lowest next total delay of the different stepper arrays, then append the master array with that difference and update all the totals accordingly, but this approach always ends up too convoluted for me to follow.

Might I offer a different solution:
Use something like freeRTOS to and make individual threads to control each motor. That way you can define delays for each motor individually without having the extra complication of making a timing array.
The ESP32 has freeRTOS available in the Arduino definitions and is pretty easy to use. You could find a port for the Teensy 4.1
Here is a really nice tutorial for blinking LEDs at different rates. Your code should have a similar approach.
freeRTOS ESP32 tutorial

Related

Generate signals with 0.1Hz resolutions using AD9833 via Arduino Uno

I would like to generate a frequency with the resolution of 0.1Hz from the range of 0.0 up til 1000.0 Hz ( Example such as 23.1 Hz, 100.5 Hz and 999.7 Hz) I have found that using AD9833 we can generate the signal as what I was required, but the notes are a bit confusing to me.
The specification can be obtained HERE .
Need your kind assist to if we can make the Arduino code.. lets say, to generate a signal of 123.4 Hz via Serial monitor from Arduino and it displayed as it is in the oscilloscope?
Thank you.
Looking at the notes, it appears that programming this chip will be non-trivial. If you don't require frequencies all the way down to 0 Hz, this job can be done much more easily with a standard Windows sound card. (Sound cards are AC-coupled, so won't go below a few Hz.) For one example, my Daqarta software can generate frequencies (with any waveform you want) at a resolution better than 0.001 Hz. The maximum frequency will be a bit less than half the sound card's sample rate... typically 20 kHz at the default 48000 Hz sample rate.
You don't have to buy Daqarta to get this capability; the Generator function will continue to work after the trial period... free, forever.
UPDATE: You don't mention what sort of waveforms you need, but note that if you can use square waves you may be able to do the whole job with the Arduino alone. The idea is to set up a timer to produce interrupts at some desired sample rate. On each interrupt you add a step value to an accumulator, and send the MSB of the accumulator to an output pin. You control the output frequency by changing the step value. This is essentially a 1-bit version of the phase accumulator approach used by the AD9833 (and by the Daqarta Generator). The frequency resolution is controlled by the sample rate and the size of the accumulator. You can easily get much better than 0.1 Hz resolution.
Best regards,

Arduino UNOv3 synchronisation of GPS and IMU MPU6050

I am relatively new with Arduino and I want to:
Set the frequency of the IMU to 100 Hz.
Synchronise GPS and MPU6050 in order to get data at the same time:
1 set of IMU data and 1 set of GPS data ->
99 sets of IMU data. (//1 second) ->
1 set of IMU data and 1 set of GPS data->
99 sets of IMU data (// 2 seconds)
I can't find anything that I can use/understand.
There are several lengthy threads in the Arduino forums for the same kind of project. Here's a good starting point. Then check out powergravity's other threads here, here, here and here. The last version of his program is here. You've got a lot of reading to do. :)
It's difficult to summarize this information into something a "new Arduino" user can "use/understand", but I'll try:
The IMU and the GPS run off their own clocks; you can set the frequency, but you can't set when they happen. Their phases or time offsets could be different. The IMU could run slightly faster or slower than 100Hz, because it is based on its own oscillator, not the GPS atomic clock (in orbit).
There will be an average of 100 IMU samples per GPS data point (an exact 1000ms). But because the IMU and GPS are not synchronized, you may get 99 or 101 IMU readings for each GPS data point.
You don't explicitly state what you are doing with the data. Whatever that is, it must accommodate the different numbers of samples per GPS period. I recommend that your loop structure is based off of the GPS time. You can even use it to measure the true frequency of the Arduino crystal (and thus the micros() clock).
At these rates, you will need to choose your GPS serial port wisely. Here are some tips.
You will also need an efficient GPS parser. My NeoGPS library is smaller, faster, more reliable and more accurate than all other libraries.

Balancing quadcopter using Arduino

I am doing a project on self balancing quadcopter with Autonomous control. I am using Arduino Mega 2560 and MPU6050. I have obtained the roll and pitch angles from MPU6050 without the help of DMP and applied complex filter to omit the noise due to vibration.
Also configured and able to run the BLDC motors with Flysky Transmitter and receiver with the help of Arduino interrupts. Now for balancing I am focusing on only one axis (i.e. roll). I have also constructed a balancing stand for the free movement of roll axis by the motor.
For the controlling part, I am implementing PID algorithm. I tried using only the kp value so that, somehow I can balance and then move on to ki and kd term. But unfortunately, for Kp itself, the quadcopter is undergoing aggressive oscillation and is not settling at all.
Some of my queries are:
Whether a single PID loop is enough, or we have to add another?
What type of tuning method I can implement, to find the kp, ki, kd other than trial and error?
I programmed my ESC for 1000 to 2000 microseconds. My PID input angles will be within the range +/- 180. Whether I can directly set the PID output limits for range -1000 to 1000 or -180 to 180 or any other value?
The code can read from the URL https://github.com/antonkewin/quadcopter/blob/master/quadpid.ino
Since its not provided, I am assuming that:
The Loop time is atleast 4ms. (The less the better)
The sensor noise is been reduced to an acceptable level.
MPU-6050 needs gyro+accel data to be combined to get angles in degrees.
If the above points are not taken care of, it will Not balance itself.
Initially, you can get away without tuning kI. So let's focus on kP and kD:
Keep increasing Kp till it starts oscillate fast. Keep the Kp value half of that.
With kP set, start experimenting kD values, as it will try to dampen the overshoots of kP.
Fiddle around these two values, tune it for perfection.
Note, the more accurate your gyro data is, the higher you can set your kP to.

Wall time dominated by setup()

I have created an OpenMDAO problem where the total wall time is being dominated by the prob.setup(). The time that it takes to call prob.run() is 10 seconds while the time that it takes to call the prob.setup() is 1916 seconds. There are 8 individual components. The root group has 20 groups with 4 subgroups of 17 subsubgroups. The total number of params is 115,021 in the whole system but almost all are 20 user inputs that are promoted throughout. I will be using this for optimization. Is there a way to speed this up, especially since all the lowest groups are using the exact same params except for like one or two? Has any testing of scalability been done for larger problems like this? It is possible to run the setup() in parallel?
We have some work getting setup times under control for some problems. Things get expensive when you have a lot of separate variables. Our usual trick is to link things into bigger array variables and have components depend on slices of the larger arrays.
Setup does work in parallel, but we haven't parallelized the setup itself.

Driving Dual 7 Segment Display Using Arduino

Okay, so I am trying to drive a 7 segment based display in order to display temperature in degrees celcius. So, I have two displays, plus one extra LED to indicate positive and negative numbers.
My problem lies in the software. I have to find some way of driving these displays, which means converting a given integer into the relevant voltages on the pins, which means that for each of the two displays I need to know the number of tens and number of 1s in the integer.
So far, what I have come up with will not be very nice for an arduino as it relies on division.
tens = numberToDisplay / 10;
ones = numberToDisplay % 10;
I have admittedly not tested this yet, but I think I can assume that for a microcontroller with limited division capabilities this is not an optimal solution.
I have wracked my brain and looked around for a solution using addition/subtraction/bitwise but I cannot think of one at all. This division is the only one I can see.
For this application it's fine. You don't need to get bothered with performance in a simple thermometer.
If however you do need something quicker than division and modulo, then bitwise operations come to help. Basically you would use bitwise & operator, to compare your value to display with patterns describing digits to be displayed on the display.
See the project here for example: http://fritzing.org/projects/2-digit-7-segment-0-99-counting-with-arduino/
You might also try using a 7-seg display driver chip to simplify your output and save pins. The MC14511BCP (a "4511") is a good one. It'll translate binary coded decimal (BCD) to the appropriate 7-seg configuration. Spec sheets are available here and they can be commonly found at electronics parts stores online.

Resources