1

I found a working code that uses pin9 (PB1) on my Arduino for controlling a Servo, but in my project, an ultrasonic sensor is already using that pin/timer. I want to convert the code to use pin6 (PD6), changed the registers according to the atmega's datasheet, but it doesn't work. Need help :/

The code should allow me to turn a servo using a potentiometer.

#define F_CPU 16000000 //16MHz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>

#define PWM_PRESCALLER 64
#define ICR_MAX (long double)F_CPU/PWM_PRESCALLER/50
#define OCR_MIN (float)ICR_MAX/37.5 // /8.75
#define OCR_MAX (float)ICR_MAX/8.7 // 37.5

volatile unsigned long adc_val=0;
volatile unsigned long counter=0;
unsigned long curr_adc=0;

ISR (ADC_vect)
{
adc_val += ADC;
counter++;
}

int main(void)
{
    DDRD |= (1<<DDD6);
    ICR1 = ICR_MAX;
    OCR0A = OCR_MIN;
    TCCR0A = (1 << COM1A1) | (1<<WGM00) | (1<<WGM01);
    TCCR0B = (1<<WGM02) | (1<<CS01) | (1<<CS00);
    ADMUX = (1 << REFS0);
    ADCSRA = (1 << ADEN)|(1 << ADATE)|(1 << ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);

    sei();
    ADCSRA |= (1<<ADSC);

    while(1)
    {
        if(counter >= 1000)
        {
            cli();
            unsigned long round_val = round(adc_val / counter);
            adc_val=0;
            counter=0;
            if(abs(round_val - curr_adc) > 1)
            {
                curr_adc = round_val; 
            }
            long double ocr = OCR_MIN + ((long double)curr_adc * (OCR_MAX - OCR_MIN)/1024);

            OCR0A = (int)round(ocr);
            sei();
        }
    } 
}
2
  • Please edit your question and try pasting the code again. Somehow there are extra newlines and all indentation was removed, making the code pretty hard to read.
    – Gerben
    Jun 10, 2018 at 17:47
  • Wouldn't it be a lot simpler to just do an analogRead each time through your loop? And use the Servo library to control the servo?
    – Nick Gammon
    Jun 10, 2018 at 22:31

2 Answers 2

1

PORTB bit 6 is controlled with TIMER0 while PORTB bit 1 is controlled with TIMER1. Therefore you need to change the timer variables appropriately. One mistake in your code is that you leave ICR1. It should be OCRA if you want to use TIMER0.

6
  • I thought of ICR0, but according to the datasheet, there is no ICR0.
    – Peti
    Jun 10, 2018 at 17:25
  • Checked that, you are right. I think you can only use OCRA. Not OCR0A?
    – MichaelT
    Jun 10, 2018 at 17:37
  • No OCRA according to Atmel studio
    – Peti
    Jun 10, 2018 at 17:41
  • Timer0 is already used for delay and millis. Use pin 3 or 11, as those use timer2 which isn't used.
    – Gerben
    Jun 10, 2018 at 17:43
  • My problem is now that I have to use ICR0 for my servo and ultrasonic sensor and then they get confused. Is there an alternative for this ICR0?
    – Peti
    Jun 10, 2018 at 18:26
-1

I agree with Nick Gammon's comment that it is a lot easier using the Arduino Platform and use AnalogRead() function in conjunction with the servo library.

Having said that, you have chosen to write the program from scratch as many others prefer to do for one reason or another. I wanted to pass on the 2 web pages that I always go to when I am playing with the PWM frequencies and setup.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.