HELP: Setting PWM other than predefined (20hz)

Is there anyway to set PWM pulsewidth other than the predefined values I found in the search?

I'm currently seeking a PWM of 20hz but the lowest i have seen so far is 30hz with

TCCR2B = TCCR2B & B11111000 | B00000111;

To get frequencies less than 30hz, you will need cycle lengths greater than 510 counts using the prescaler of 1024 with a 16 mhz processor. That can not be done on an 8 bit timer.

You will have to do this on timer 1 with one of the pwm modes which lets you define a total cycle count of 781 or 782 to get to a 50 ms period. Your top count will be half that value if you use a phase correct pwm mode.

I would advise spending some time with the data sheet for the ATmega 328 to help select the proper mode and top level.

wow i hope not too much time over on that sheet. New to arduino much less lower level stuff.

There is no need to get into the low level stuff for basic pulse generation. You can use digitalWrite() to turn an output on and off, and use the techniques of "Blink Without Delay" to control the timing. Here's an example for 20Hz pwm.

//Simple software pwm generator 20Hz

const byte pulsePin = 2; //pin sending pulses

//50000 microseconds total period for 20Hz
byte dutyCycle = 35;//percent time on value 1-99
unsigned int pulseHigh = dutyCycle*500; //High time micros for duty cycle
unsigned int pulseLow = 50000 - pulseHigh; //Low time micros
unsigned int pulseTime = 0; //next interval high or low
unsigned long currentTime;//time from micros()
unsigned long lastTime;//last time the pulse pin changed state
byte pinState = LOW;// pulsePin state

void setup()
{
  pinMode(pulsePin, OUTPUT);
}

void loop()
{
  currentTime = micros();
  if (currentTime - lastTime >= pulseTime)
  {
    lastTime = currentTime;//restart timing period

    if (pinState == LOW)
    {
      pinState = HIGH;
      pulseTime = pulseHigh;
    }
    else
    {
      pinState = LOW;
      pulseTime = pulseLow;
    }
    digitalWrite(pulsePin, pinState);
  }
}

I had code like that before, only difference you are using the MCU's ticks to keep control of time. I have found nick gammon's post:

 TCCR1A = _BV (COM1A0);  // toggle OC1A on Compare Match
  TCCR1B = _BV(WGM12) | _BV(CS10) | _BV (CS12);   // CTC, scale to clock / 1024
  OCR1A =  4999;       // compare A register value (5000 * clock speed / 1024)

which would have it at 3.x hz, but it turns on the pin without loop. Now how can i use the 3.x hz, or 25hz by turning it on and controlling duty cycle in the loop section like so:

analogWrite(LED, 127); //50% duty

and then work with pin 9 {gonna have to modify my PCB (not neat!)

Pin 9 uses OCR1A so it can't be used as a pwm output when you use that value as a top count.

Other than a 20 hz pulse, you haven't said what you are trying to do, or what precision you require. Can you please provide some more details on your application.

You can be using pin10 as an output with hardware control. but you will have more options for it with a pwm mode rather than ctc.

If you want to use any pin for your pwm, it may be possible to use an output compare interrupt on OCR1B to turn the pin on within the compare match isr , and then an overflow interrupt to turn it off in a second isr at the end of the 50 ms period. With direct port manipulation within the isr's, it could be quite fast, but not as quick as using one of the timer output pins driven in hardware.

THanks for responding.

I'm trying to pulse a makeshift injector. The predefined 31hz i got using
TCCR2B = TCCR2B & B11111000 | B00000111; //PWM

is still a bit too fast for that coil, at low duty cycles <15% or high duty cycles >80% the coil 'misfires'
So it is my intention to slow it down. So far, I gather that the pin I'm using (Digital 3) is from 8bit controller, so i have to move to a 16bit one. I'm now wondering how i can do this. I have little knowledge of the interrupts and what is happening.

I found the solution using a PWM library found here:

http://forum.arduino.cc/index.php?topic=117425.0

It works flawlessly, just had to change to pin 10 on my board.

Thanks for those who took the time to respond.

Additionally, you could still answer the question by showing how to do this in 3 or 4 lines (as i suspect it could be done without library)

With what you are trying to do with the injector, and your level of experience with the Arduino, I would recommend that you stick with software generation of pulses for the present, and not use the hardware timer/counters. At the frequencies you are using, there is plenty of processor speed to do what you want with software, and you do not need the precision or background operation of the timers.

I don't know what you mean by "makeshift injector", but perhaps you could figure out the cause of the slow switching time so that you can get it operating at the 30hz you can achieve on an 8 bit timer with the standard analogWrite commands with the change of prescaler that you used originally.

Here is why I can't do that. The LCD write has irregular delays in the loop cycle, causing the injector's duty cycle (code generated) to be inaccurate at some times. If there is a '"block" in the loop cycle the injector may stick open and flood the engine.

Makeshift injector is a fuel injector using a solenoid and a nozzle, instead of a real fuel injector.
The reason it sticks is because the spring in the solenoid is not stiff enough, but i can't go stretch it to stiffen it as the electromagnetic field would also have to be strong enough to overcome that stiffness to open and close the valve. Think of it as valve floating when a car's RPM is too high.

gonna share a video with it at 20 hz.

Maybe a dumb question, but doesn't an injector have to be synchronized with the piston cycle?

aarg:
Maybe a dumb question, but doesn't an injector have to be synchronized with the piston cycle?

No question is a dumb question :).

For cylinder based injectors, yes. But for induction pipe injector (5th injector for example) you can scale it based off the Mass Air flow sensor voltage (MAFv), manifold pressure and RPM (to get the engine "load")

This will be a water injection controller. I'm scaling mine off the MAFv with a predefined boost pressure as the trigger point, and a predefined MAFv as the initial spraying point. All of this would have to be calculated using logs from the car's ECU to determine the perfect entry point to begin spraying.

video: http://www.youtube.com/watch?v=cL-n25_Y2U8

The LCD write has irregular delays in the loop cycle

I took a look at the video, and it looks like an interesting project. It appears you are using a 20x4 i2c lcd display.

You should be able to write non blocking display code. If you stay away from lcd.clear() and only update or overwrite changing portions of the display, you can be fast enough for the 20Hz.

It may be worth doing that even if you have found a library solution for timer1 use with pin 10. With all that you will have going on in your final code, you don't want the display getting in your way.

Why would you inject water into a running internal combustion engine?

Look up water injection or methanol injection

Yeah. I've also opted to use a small 1 inch TFT LCD which will be fitted in a gauge. Will post the final prototype.