Hello,
I am using arduino nano, for reading a Voltage, attached to A7 pin.
Based on that voltage level, the arduino has to start generating PWM signals (0~255) out from the digitals IOs. I already know, that there are dedicated PWM pins, but they are aleardy assigned for another operations, and I have used D2,D4,D7 though, as pins, supposed to generate PWMs.
Is there a way, to generate specific PWMs, out of D2 for example, controlling its duty cycle and frequency?
Study Servo.h Library's source codes and see the mechanism of PWM signal generation on any valid Digital pin. Currently the library generates 50 Hz signal with varying duty cycle.
I will have a look. But in respect to frequency, It will be good to be within 490-980Hz or something like that. It will be switching mosfets, and 50Hz is a very slow rate.
To produce PWM on non-hardware PWM pins, you have to use a timer and direct digital writes to the pin. Here is a good timer tutorial: https://www.gammon.com.au/timers
You will never obtain the accuracy, full possible speed, and output range with an emulation like this, as you would with a PWM hardware supported pin.
What are the "other operations" that the usual PWM pins are dedicated to? It might be easier to just change them.
Is this for a servo? The servo protocol is restricted in frequency and PWM range, so it's more permissive (easier to implement this way) than general purpose PWM.
Hi aarg,
Actually the Nano board is already soldered to a PCB, so there is no chance to change the wiring. All digital IOs from D2 up to D8, are responsible for generating PWMs, but unfortunately, only pin# 3, 5, 6 are capable of doing so, thus I am loosing pin#2,4,7,8 as position on the board, as I do not know how to drive them properly, this is what I am asking for.
Nothing related to servo, it is all about driving mosfets independently, for switching loads.
If possible isolate D9 or D10 by nicely cutting the PCB track with sharp blade and then put soldered jumpers as needed. You will be able to generate PWM signals using TC1.
Of course that will work,
But I wrote here, asking for help, to be able to do it smarter than cutting the tracks.
If there is no way to drive and control the PWM out of a non-PWM dedicated pin, then it seems I have to a
re-design and to use only 3, 5, 6, 9, 10 and 11. Which is a kind of a limitation, since I have to drive 7 mosfets, having only 6 PWM outpus....
Perhaps a better design process would have been to determine the capabilities of the device first,
test some of the operation on a breadboard, and design the PCB when all else is proved to work?
Why not post a schematic showing what you have connected to each of the nano's pins?
Here's how Joop Brokking calculated the pulse outputs, to control 4 brushless dc motors on his multi-rotor/drone flight controller with a 250Hz update rate. Note that his code simply bit bangs the output pins in the loop(), with timing provided by the micros() function:
//All the information for controlling the motor's is available.
//The refresh rate is 250Hz. That means the esc's need there pulse every 4ms.
while(micros() - loop_timer < 4000); //We wait until 4000us are passed.
loop_timer = micros(); //Set the timer for the next loop.
PORTD |= B11110000; //Set digital outputs 4,5,6 and 7 high.
timer_channel_1 = esc_1 + loop_timer; //Calculate the time of the faling edge of the esc-1 pulse.
timer_channel_2 = esc_2 + loop_timer; //Calculate the time of the faling edge of the esc-2 pulse.
timer_channel_3 = esc_3 + loop_timer; //Calculate the time of the faling edge of the esc-3 pulse.
timer_channel_4 = esc_4 + loop_timer; //Calculate the time of the faling edge of the esc-4 pulse.
while(PORTD >= 16){ //Stay in this loop until output 4,5,6 and 7 are low.
esc_loop_timer = micros(); //Read the current time.
if(timer_channel_1 <= esc_loop_timer)PORTD &= B11101111; //Set digital output 4 to low if the time is expired.
if(timer_channel_2 <= esc_loop_timer)PORTD &= B11011111; //Set digital output 5 to low if the time is expired.
if(timer_channel_3 <= esc_loop_timer)PORTD &= B10111111; //Set digital output 6 to low if the time is expired.
if(timer_channel_4 <= esc_loop_timer)PORTD &= B01111111; //Set digital output 7 to low if the time is expired.
}
Obviously this won't be as precise as hardware PWM outputs, but might be good enough for your 7th pin?