I am making a robot that moves in a circle with two wheels, each wheel move using a DC motor with 12 volts. I want a relation between the circle and the voltage that is produced by Pulse Width Modulation.
Basically there's no generic formula for relating PWM to wheel movement. There are too many variations taking place depending on which motors you choose, which wheels, what gear ratio, the voltage of the battery and how many amps the batteries can supply, etc.
Instead, you can make an estimate by measuring the performance of your specific chassis (e.g. combination of all of the above) and either using a single constant (e.g. PWM Power * 0.432 == Wheel movement in linear cm at full charge) or better yet using a series of constants that estimate based on PWM power (e.g. 0.123 # 50/255 PWM duty cycle, 0.389 # 200/255 PWM duty cycle) and also vary based on current battery charge levels (e.g. 0.123 # 50 PWM # 12.1v charge, 0.089 # 50 PWM # 10.7v charge). As you can see, even 'simple' estimation gets complex quickly.
This is why you see people use encoders -- encoders basically measure 'real world' wheel movement irregardless of all the variables. You can use your encoders to measure how fast your wheels are turning based on the current PWM duty cycle and then just vary up or down the PWM output based on the speed/distance you want.
Related
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
I am testing GRBL for laser cutting..
In (defaults.h), i set default velocity to 40000mm/min, and default acceleration to 4000mm/sec2.
#ifdef DEFAULTS_GENERIC
// Grbl generic default settings. Should work across different machines.
#define DEFAULT_X_MAX_RATE 40000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 40000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 40000.0 // mm/min
#define DEFAULT_X_ACCELERATION (4000.06060) // 106060 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Y_ACCELERATION (4000.06060) // 106060 mm/min^2 = 10 mm/sec^2
#define DEFAULT_Z_ACCELERATION (4000.06060) // 106060 mm/min^2 = 10 mm/sec^2
In (config.h) i define machine configuration.
#define DEFAULTS_GENERIC
in G-Code i set feed rate to 20000mm/min (F20000).
But i get very slow move movements, anybody knows why?
First I would check your hardware juper setup since usually it is possible to use the so called microsteps that in fact multiplies the number of steps needed for 1 stepper motor revolution by 2,4,8,16... Second you need to check the number of steps per revolution of your stepper motor (usually is 200, but are commonly used also 4,8,16..400 variants). Then see the diameter of your pulleys to calculate the linear movement done by the machine for one revolution of your stepper motor. You are ready now to do your math to adapt the variable settings to your hardware.
Moreover, once you have done your math, maybe, you will realize that your parameters are too high for your machine and the stepper motors simply are not able to keep up with the high rate of pulses that you are sending to them. This is why, maybe, your motors are turning slowly. At last, I would check your power supply to be sure that you are providing the correct voltage and current to your motor: this may be another reason why your motors are turning slowly.
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,
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.
X:471 Y:486 Z:476
X:468 Y:478 Z:467
X:454 Y:460 Z:450
X:436 Y:435 Z:422
X:392 Y:379 Z:364
X:327 Y:305 Z:296
X:270 Y:248 Z:250
X:248 Y:236 Z:246
X:260 Y:258 Z:269
X:292 Y:297 Z:307
X:321 Y:331 Z:341
X:375 Y:398 Z:406
X:439 Y:465 Z:465
X:478 Y:502 Z:494
X:489 Y:503 Z:491
X:478 Y:487 Z:475
X:462 Y:465 Z:451
X:413 Y:401 Z:385
X:343 Y:321 Z:313
X:272 Y:247 Z:249
X:253 Y:239 Z:248
X:260 Y:256 Z:268
X:288 Y:293 Z:304
X:320 Y:330 Z:340
X:374 Y:394 Z:400
X:436 Y:464 Z:463
Here is my sample of data (Not moving at all) I don't know what can i do with all these data.
I wrote a blog post about this device on an Arduino that should answer your questions.
http://chrisheydrick.com/2015/02/05/adxl335-accelerometer-on-an-arduino/
In short, the values you're seeing depend on the power delivered to the ADXl335.
The sensitivity (mV/g) is stated to be ratiometric in the data sheet, and the example given is that when you deliver 3V to the power supply, the sensitivity is 300 mV/g. In a later section called “Use with operating voltages other than 3V” it gives the example of 360 mV/g with a 3.6V power supply, and 195 mV/g with a 2V power supply. You can pretty much gather that the sensitivity in mV/g is the power supply voltage divided by 10. More or less.
Another ratiometric value is the “0g bias”. The accelerometer chip can detect negative acceleration, but it doesn’t output a negative voltage signal. What you do is consider the middle point of the power supply voltage range the 0 point. My power supply voltage is 3.3V, so I have to treat 1.6V as the zero point. You’ll add have to subtract that zero point from any voltage reading to get the actual mV/g value.