User Timer1's Overflow for PWM on pin 3

Hello,

Like the title suggests, I'm trying to use Timer1's overflow on pin3. I am using an Arduino Ethernet. I want to get my output PWM at 200 Hz. I am going to use Fast PWM with ICR1 as my TOP. In other words, WGM13:0 = BV(1 1 1 0).

I looked at the atmel spec sheet and I can set the 16Mhz Arduino clock to a fast PWM at 8 MHz. I then found out that there are 40,000 8MHz in one 200 Hz pulse. This allows me a .125 usec resolution.

I then set my limits between 900 usec and 2100 usec. Using the resolution to determine the number of 8MHz pulses, I found that 900 usec is 7200 pulses and 2100 usec is 16800 pulses. In other words, the number of 8Mhz pulses = (desired PW)*8.

I am using TIMER1_OVF_vect as the interrupt to control the PW of the servo. Currently, it is set to 12000 for testing purposes but I have code which can change the pulse width for later versions. The current one is a simple if... else if loop, where if the counter is equal to the cut number of 8Mhz pulses (12000), go low, else if counter is equal to the period (40000), go high and set counter to 0.

Below is my code. I am a bit unsure on what I want for TIFR1 and TIMSK1 to be. However, I've noticed when I change the TIFR1 registry, that the Serial communication stops to the Arduino.

Can someone please help me with what is wrong with my code? To make the registry stuff easier, CS = 1, WGM = 14, TIMSK1 is unchanged and TIFR1 is unchanged.

//Code example for Arduino Uno by Ukeri 
//Bart Borghuis and Zoomkat wrote the majority of the code that I used, I just changed it to what I needed.
//Zoomkat's "servo-test-22-dual-input"'s void loop() is my void loop() code
//This program drives a servo motor using timer1 interrupts at 200Hz.
//The Ethernet code is used to change the SS of SPI from 10 to 3 - Code from SurferTim - and test if servo can still
//be controlled on pin 10.


// Done for servo control
#include <avr/interrupt.h> 
#include <Serial.h>

//storage variables
String readString;
volatile unsigned int pin3_PW=12000, pin3_diff=0, pin9_PW=12000, pin9_diff=0, period=40000, counter=0; // Tilt 


// Initialize Ethernet stuff


void setup(){
  //allows serial communication with the Arduino
  Serial.begin(9600); 
  //set pins as outputs
  pinMode(3, OUTPUT); 
  pinMode(9,OUTPUT);
  
  Serial.println("pre registry output");
  Serial.print("TCCR1A: ");
  Serial.print(TCCR1A);  
  Serial.print("  TCCR1B: ");
  Serial.print(TCCR1B);  
  Serial.print("  TCCR1C: ");
  Serial.print(TCCR1C);
  Serial.print("  TIMSK1: ");
  Serial.print(TIMSK1);
  Serial.print("  TIFR1: ");
  Serial.println(TIFR1);  
  
  delay(500);
  cli();//stop interrupts
  //Initialize the registries for 8 MHz
  ICR1 = 0x1;
  TCCR1A = 0x2;    // BV(0 0 0 0 0 0 1 0)
  TCCR1B = 0x19;   // BV(0 0 0 1 1 0 0 1)
  TCCR1C = 0x0;    // BV(0 0 0 0 0 0 0 0)
//  TIFR1 = 0x1;     // BV(0 0 0 0 0 0 0 1)
//  TIMSK1 = 0x1;    // BV(0 0 0 0 0 0 0 1)
  
  TCNT1  = 0;//initialize counter value to 0

  sei();//allow interrupts
  
  counter=0;
  Serial.println("servo registry control - Interrupt - custom 4MHz signal - Fast PWM mode"); // so I can keep track of what is loaded  
  Serial.print("TCCR1A: ");
  Serial.print(TCCR1A);  
  Serial.print("  TCCR1B: ");
  Serial.print(TCCR1B);  
  Serial.print("  TCCR1C: ");
  Serial.print(TCCR1C);
  Serial.print("  TIMSK1: ");
  Serial.print(TIMSK1);
  Serial.print("  TIFR1: ");
  Serial.println(TIFR1);  
  
  
}//end setup


void loop()
{
  Write_serial_data(pin3_PW);  // Writes to pin 10
}
 
 
 
 
 void Write_serial_data(unsigned int PW)
{
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) 
  {
    Serial.println(readString);  //so you can see the captured string 
    int n = readString.toInt();  //convert readString into a number

    // determines if the input is within the range of the servo.
    if(n >= 900 && n <=2100) // input is within the range of the servo
    {
      PW = n * 8;  // takes input pulse width and converts it to a value for OCR1A
    }
    else if(n < 900)  // input is too small
    {
      n=900;
      PW = n * 8; // takes input pulse width and converts it to a value for OCR1A
    }
    else if(n > 2100)  // input is too large
    {
      n = 2100;
     PW  = n * 8; // takes input pulse width and converts it to a value for OCR1A
    }

    readString=""; //empty for next input
    }
    
//    Serial.print("counter: ");
//    Serial.println(counter);
}




 
ISR(TIMER1_OVF_vect)
{
  counter++;
  if(counter = pin3_PW)
  {
    digitalWrite(3, LOW);
  }
  else if(counter = period)
  {
    digitalWrite(3, HIGH);
    counter = 0;
  }
    
}

Thanks,
Matt

 if(counter = pin3_PW)

==

MarkT,

Thanks for pointing that out, I over looked it >.<

Unfortunately, that did not solve my problem. I'm was looking at some old code I wrote and I noticed that I set up pretty much the same, but with a higher ICR1. It was at ~0x4000. I then wanted to see if my code would work with me having a higher ICR1, so I set it to 0x1000 - just an arbitrary number to see if my counter was being updated.

Note. I have a counter++ in the ISR(TIMER1_OVF_vect) part of the code and in the main loop I have a Serial.println(counter) statement. This has been my method of checking if everything is working.

It did update the counter and when I was looking at the serial output, I found it worked properly.

Could it be that I am updating the Arduino too fast for it to do anything else BUT the timer overflow? Im thinking about trying a fast phase PWM timer - 4 MHz - and if that doesnt work, do math to figure out what values would give me a .5usec resolution. I feel like that is the slowest I can update a servo reasonably.

Matt