Servo code didn't work...

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I attached 2 servos on D9 and D10 of Arduino UNO, the servo example of Servo library works, but my code didn't, could anyone here tell why?

 

void setup() {
  // put your setup code here, to run once:
  TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11)|(1<<COM1A0)|(1<<COM1B0);        //NON Inverted PWM 
  TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS11)|(1<<CS10); //PRESCALER=64 MODE=14(FAST PWM)
  DDRB = (1<<PB1)|(1<<PB2);   //PWM Pins as Output
  ICR1=4999;  //fPWM=50Hz  
}

void loop() {
  OCR1A = 250;
  delay(1000);
  OCR1A=375;
  delay(1000);
  OCR1A = 500;
  delay(1000);

  OCR1B = 250;
  delay(1000);
  OCR1B = 375;
  delay(1000);
  OCR1B = 500;
  delay(1000);
}

and

void setup() {
  // put your setup code here, to run once:
  TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11)|(1<<COM1A0)|(1<<COM1B0);        //NON Inverted PWM 
  TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS11); //PRESCALER=8 MODE=14(FAST PWM)
  
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);

  ICR1=40000;  
}

void loop() {
  OCR1A=2000;
  delay(1000);
  OCR1A=3000;
  delay(1000);
  OCR1A=4000;
  delay(1000);

  OCR1B = 2000;
  delay(1000);
  OCR1B = 3000;
  delay(1000);
  OCR1B = 4000;
  delay(1000);
}

 

Last Edited: Thu. Nov 25, 2021 - 02:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MianQi wrote:
my code didn't

what, exactly, did it do?

 

what investigation / testing / debugging have you done to find what's going on ?

 

MianQi wrote:
the servo example of Servo library works

so have you dome a compare-and-contrast with that code against yours ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I simulated in thinkercad, it didn't work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found this thread, it works:https://www.avrfreaks.net/forum/...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, i tested it just now in Arduino IDE, it didn't work either, it just works in thinkercad simulator.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First off.   Write in human readable form e.g. your second example:

void setup()
{
  // use = instead of |=, use field values, correct comments
  TCCR1A = (2<<WGM10)|(3<<COM1A0)|(3<<COM1B0);  //WGM=14 (Fast PWM), Inverted OC1A,OC1B
  TCCR1B = (3<<WGM12)|(2<<CS10); //WGM=14 (Fast PWM), PRESCALER=8

  pinMode(9, OUTPUT);  //OC1A
  pinMode(10, OUTPUT); //OC1B

  ICR1 = 40000;   // a very big TOP value. Freq = 16MHz/8/40k = 50Hz. Period = 20ms
}

Untested.  It looks ok to me.   I would probably use div64 with ICR1 = 50 5000.  

It depends on the granularity that you desire.  You only seem to want tiny duty cycles 2.5%, 5%, 7.5%, 10%.

 

Oh,   the argument for field values in multi-bit fields is weak when WGM1 is split between two special function registers.

It is very strong for single group like CS1

No human being can understand random individual bitfields.   Especially when written in a random order.

 

David.

Last Edited: Fri. Nov 26, 2021 - 08:49 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MianQi wrote:
I simulated in thinkercad, it didn't work.

So, again, what investigation / testing / debugging have you done to find what's going on ?

 

EDIT

 

How To Debug

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Nov 26, 2021 - 08:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MianQi wrote:
thinkercad (sic?)

Did you mean this: https://www.tinkercad.com/ ?

 

it didn't work

Simulations are never exact - so it could be a limitation of the simulator. Have you tried their "Help Centre": https://tinkercad.zendesk.com/hc/en-us/categories/200357447-FAQ

 

The simulation will also assume perfect/ideal components - it won't know about any issues or errors with your physical setup...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am intrigued.  So I wrote an AS7.0 project.   And viewed the result via a Saleae Logic Analyser.

It behaves exactly as expected.  i.e. Period = 20ms.  Inverted PWM.  Duty Cycle 2.5% - 10%.

 

Obviously this is fine as electronics.   Not much good for an RC Servo that expects non-inverted PWM with duty cycles 0 - 10%.

If the OP concentrated on writing intuitive initialisation code with accurate comments,  she would have everything working first time.

 

I have no idea what Thinkercad is.   Does it know how a real-life Servo works ?

If you want non-inverting mode,  use COM1A=2, COM1B=2 i.e. from Table 15-2. Compare Output Mode, Fast PWM

 

#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>

#define delay(ms) _delay_ms((ms)/10)   //easier to capture shorter bursts.

void setup()
{
    // use = instead of |=, use field values, correct comments
    TCCR1A = (2<<WGM10)|(3<<COM1A0)|(3<<COM1B0);  //WGM=14 (Fast PWM), Inverted OC1A,OC1B
    TCCR1B = (3<<WGM12)|(2<<CS10); //WGM=14 (Fast PWM), PRESCALER=8

    DDRB |= (1<<PB1);  //OC1A
    DDRB |= (1<<PB2); //OC1B

    ICR1 = 40000;   // a very big TOP value. Freq = 16MHz/8/40k = 50Hz. Period = 20ms
}

void loop() {
    OCR1A=2000;
    delay(1000);
    OCR1A=3000;
    delay(1000);
    OCR1A=4000;
    delay(1000);

    OCR1B = 2000;
    delay(1000);
    OCR1B = 3000;
    delay(1000);
    OCR1B = 4000;
    delay(1000);
}

int main(void)
{
    setup();
    while (1)
    {
        loop();
    }
}

 

Last Edited: Fri. Nov 26, 2021 - 10:44 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

    // use = instead of |=, use field values, correct comments
    TCCR1A = (2<<WGM10)|(3<<COM1A0)|(3<<COM1B0);  //WGM=14 (Fast PWM), Inverted OC1A,OC1B
    TCCR1B = (3<<WGM12)|(2<<CS10); //WGM=14 (Fast PWM), PRESCALER=8

Just playing devil's advocate, you might want to explain why you then go on to use |= here:

    DDRB |= (1<<PB1);  //OC1A
    DDRB |= (1<<PB2); //OC1B

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Since we are being educational.

 

PORTB has many uses.   You do not want to change the other pins.  You only need to configure the OC1A, OC1B pins.   So |= is appropriate.

 

Yes,  since this is a trivial example,  you could just say

    DDRB = (1<<PB1)|(1<<PB2);  //OC1A, OC1B output.  Every other PORTB pin is forced to input.

God gave you = , |= , &=~ , ^=

Just use the appropriate assignment operator when required.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David, you are right, when I altered to avr-gcc chain in CMD, the Timer works.

 

Now, the problem is ADC:

    float reading = 0;
    
    if(knob == 1){
    ADMUX |= (1<<MUX0);
    ADMUX &= 0b11110001;
    } else if(knob == 0){
    ADMUX &= 0b11110000;    
    }
    
    int readingInterH = 0;
    int readingInterL = 0;
    int readingInter = 0;
    ADCSRA |= 1<<ADSC;
    readingInterH = ADCH;
    readingInterL = ADCL;

    readingInter = (ADCH<<8)|ADCL;
    readingInter = readingInter>>6;
    reading = readingInter / 1023.0;

Did I lost anything?

Last Edited: Sat. Nov 27, 2021 - 09:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MianQi wrote:
the problem is ADC

What is the problem with the ADC?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why are you using float? Why on earth are you fooling around with 4 DIFFERENT VARIABLES to take an ADC reading??????

 

The ADC supplies an integer from 0 to 1023?  You just need to read the entire ADC value all at once into an integer variable...the compiler knows how to read 16 bit registers (don't read high & low bytes separately). 

Do some serious thinking and use the integer values in your calculations.   You rarely need any floating point anywhere, even for calculating.  You can perform a simple conversion (scaling)  process, if you need to display something. 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Nov 27, 2021 - 04:23 PM