High freqency pwm timer4 Mega- am I missing anything

Hello :slight_smile:
As part of a project I am trying to use a proportional solenoid requiring around 20KHz PWM.

Given the Arduino Mega PWM frequency is around 500Hz I though bit manipulation will be the way to go:

Here is the code i wrote :



void setup() 
{

  /// we will try to use timer4

TCCR4A = 1 << COM4A1 | 0 << COM4A0 | 1 << WGM41 | 0 << WGM40; // SET COM4A1 TO 1 COM4A0 TO 0 :Clear OCnA on compare match, set OCnA at BOTTOM (non-inverting mode)
// WGM41 is set to 1 so we will work with TOP of ICR4 mode 14
    TCCR4B = 1 << WGM43 | 1 << WGM42; //settin those for fast PWM mode 14 - reqires 1 1 1 0

    // 20 kHz at 16Mhz
    ICR4 = 799;  // Sets TOP value for Timer4 - 16milion ticks in a sec * with period of 50 microsec =800 ticks

    // 50% duty cycle
    OCR4A = 400;  // Sets duty cycle for Channel A (OC4A pin)

    TCNT4 = 0;    // Initialize the counter

    // Start Timer4 at 16MHz (no prescaling)
    TCCR4B = 1 << WGM43 | 1 << WGM42 | 0 << CS42 | 0 << CS41 | 1 << CS40;
    pinMode(6, OUTPUT);
}

void loop() 
{
}

I have no prior experience doing something like this so feel free to explain if I did anything wrong.
The way i see it is we set TCCR4A register to clear OC4A on compare match so we are HIGH until OCR4A values is ticked then we are LOW and continue to count till ICR4 values is reached.
Then the counter is initialized using TCNT4 =0 and then we start the count when we initialize the clock by setting 0 << CS42 | 0 << CS41 | 1 << CS40.
At the end I set the relevant pin to output so I will be able to get an output in the relevant pin.

Have i done anything wrong? I currently have no scope to validate this.
I did not find which functions uses timer4 so i used him - is there a problem by doing so?
Mega pin mapping :

thanks !

Please give the data sheet for that solenoid. Typically solenoids work with PWM of about 100 Hz, with jitter against sticking.

proportional solenoid from Gevasol P377:
USER MANUAL
Data sheet

as per a email exange I had with someone from the manufacturer : "generating a PWM signal with a current control. If you use a PWM, please set the frequency ideally around 20 kHz but at minimum 3kHz."

Your code looks correct to me.

This line is duplicated and completed below again. Drop it and merge the comments about timer and prescaler mode..

i agree, in my understating only when i set 0 << CS42 | 0 << CS41 | 1 << CS40; the actual counting starts, that is why i did not incorporate that section in the first instance of TCCR4B.
i believe though that i can only use something like:

TCCR4B = 0 << CS42 | 0 << CS41 | 1 << CS40;

instead of the repeated part.

No, all bits have to be set in one assignment.

oh ok, so i can only write it once at the end
like this?

TCCR4A = 1 << COM4A1 | 0 << COM4A0 | 1 << WGM41 | 0 << WGM40; // SET COM4A1 TO 1 COM4A0 TO 0 :Clear OCnA on compare match, set OCnA at BOTTOM (non-inverting mode)
// WGM41 is set to 1 so we will work with TOP of ICR4 mode 14
    
    // 20 kHz at 16Mhz
    ICR4 = 799;  // Sets TOP value for Timer4 - 16milion ticks in a sec * with period of 50 microsec =800 ticks

    // 50% duty cycle
    OCR4A = 799;  // Sets duty cycle for Channel A (OC4A pin)

    TCNT4 = 0;    // Initialize the counter

    // Start Timer4 at 16MHz (no prescaling)
    TCCR4B = 1 << WGM43 | 1 << WGM42 | 0 << CS42 | 0 << CS41 | 1 << CS40;
    pinMode(6, OUTPUT);

You miss how important the intended timer mode and prescaler setting are for the reader of that code.

i am not sure what you meant by that.
can you clarify that?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.