Problem with tinkercad WGM13

Hello, I have the next code:

// Variable for the angle of the servo motor, ranging from 0 to 180 degrees
int grade = 0;
int contor = 0;

void setup() {

  // Set pin 9 (OC1A) as an output
  DDRB |= (1 << PB1);
  
  // Set up Timer 0 to count time at the interrupt frequency of 250Hz, every 0.004s
  TCCR0A = (1 << WGM01) | (0 << WGM00);
  OCR0A = 0xF9;
  TIMSK0 |= (1 << OCIE0A);
  TCCR0B = (1 << CS02) | (0 << CS01) | (0 << CS00);

  // Set up Timer 1 to generate a PWM signal with a frequency of 50Hz, every 20ms
  TCCR1A = (1 << COM1A1) | (1 << COM1B1); // Non-inverted Mode
  TCCR1B = (1 << WGM13) | (1 << CS11); // Prescaler 8
  ICR1 = 20000; // TOP = F_CPU/2*Prescaler*50Hz
  OCR1A = 0; // PWM duty cycle register

  // Enable global interrupts
  SREG |= (1 << SREG_I);
}

void loop() {

  // Set the PWM duty cycle
  OCR1A = convertAngleToPWM(45);
}

ISR(TIMER0_COMPA_vect) {
  // Disable global interrupts
  SREG &= ~(1 << SREG_I);

  ++contor; // Increment the counter

  if (contor >= 100000)
    contor = 0;

  // Enable global interrupts
  SREG |= (1 << SREG_I);
}

// Function to convert angle to PWM value
int convertAngleToPWM(int angle) {
  // The motor operates with pulses between 0.5ms and 2.5ms, so a 2ms interval corresponds to 2000 increments in OCR1A
  // If we have 500 increments for angles from 0 to 45 degrees, to convert the angle to the corresponding register value
  // we calculate 500/45, which results in multiplying each degree by 11.1111 and then adding the starting value of 500
  float a = 11.1111;
  float b = 500;

  return int(a * angle + b);
}

in tinkercad with this drawing:

and I don't understand why my code is freezing after the line:
TCCR1B=(1<<WGM13)|(1<<CS11);//Prescalar 8

Could anyone help me please?!?!?!

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum

Who suggested you to touch the timer 0 which is required for housekeeping? Also your ISR is poorly coded.

Your picture does not compute. Why the black thing. What is the fan like thing? I highly recommend you go back and read a few posts on this forum and many others about connecting motors to an arduino. You should come across two important rules:
Rule #1 An Arduino is NOT a Power Supply!
Rule #2 Never connect anything inductive to an arduino!
Maybe rule 3 should be if you fail on rule 1 or 2 have a spare pile of Arduinos.

That is the representation of a "servo".

Interesting mine do not look like that.

Less than 3 minutes --

image

I have found this helpful

I know it's poorly coded, but the first thing I want to fix is why my code freezes when I connect pin 9 to anything.

Thank you very much; I find this repository and its website very useful. I will try it immediately. Thanks!

The code still freezes at the setup of TCCR1B in Tinkercad. Why does this happen? (I am now using pin 10 to control the servo motor, but when I connect pin 10 to the servo motor, Tinkercad freezes.)

void setup(){
  SREG &=~ (1<<SREG_I);
  TCCR1A = 
    1 << COM1B1 |
    1 << WGM11;
  TCCR1B = 
    1 << WGM13 |
    1 << CS11;
  DDRB = 
    1 << DDB2;
  OCR1B = 0;
  ICR1 = 20000;
  SREG |= (1<<SREG_I);
}

Your code works fine.
It generates a 1005us servo pulse on pin9.

You were not using the ISR at all, so I made a few changes to use the ISR to move the pulsewidth slowly from 500 >> 2500 us, as that was mentioned in the formula description.

Keep in mind that you need to adapt the formula if you want a 1000 - 2000 us PWM pulse, which is the default servo range.
500 - 2500 us has some servo overtravel at both ends. Not all servo's can deal with that, but that is a matter of testing

// Variable for the angle of the servo motor, ranging from 0 to 180 degrees
//int grade = 0; // not used
volatile int contor = 0; // needs volatile as changed inside ISR

void setup() {

  // Set pin 9 (OC1A) as an output
  DDRB |= (1 << PB1);
  
  // Set up Timer 0 to count time at the interrupt frequency of 250Hz, every 0.004s
  TCCR0A = (1 << WGM01) | (0 << WGM00);
  OCR0A = 0xF9;
  TIMSK0 |= (1 << OCIE0A);
  TCCR0B = (1 << CS02) | (0 << CS01) | (0 << CS00);

  // Set up Timer 1 to generate a PWM signal with a frequency of 50Hz, every 20ms
  TCCR1A = (1 << COM1A1) | (1 << COM1B1); // Non-inverted Mode
  TCCR1B = (1 << WGM13) | (1 << CS11); // Prescaler 8
  ICR1 = 20000; // TOP = F_CPU/2*Prescaler*50Hz
  OCR1A = 0; // PWM duty cycle register

  // Enable global interrupts
  SREG |= (1 << SREG_I);
}

void loop() {

  // Set the PWM duty cycle
  OCR1A = convertAngleToPWM(contor/100);
}

ISR(TIMER0_COMPA_vect) {
  // Disable global interrupts
  SREG &= ~(1 << SREG_I);

  ++contor; // Increment the counter

  if (contor >= 18000)
    contor = 0;

  // Enable global interrupts
  SREG |= (1 << SREG_I);
}

// Function to convert angle to PWM value
int convertAngleToPWM(int angle) {
  // The motor operates with pulses between 0.5ms and 2.5ms, so a 2ms interval corresponds to 2000 increments in OCR1A
  // If we have 500 increments for angles from 0 to 45 degrees, to convert the angle to the corresponding register value
  // we calculate 500/45, which results in multiplying each degree by 11.1111 and then adding the starting value of 500
  float a = 11.1111;
  float b = 500;

  return int(a * angle + b);
}

Thank you for all your help, but I need to complete the project in Tinkercad, and the frustrating issue with WGM13 is causing the entire debugging process to freeze, which is driving me crazy!

Ok. In that case you can better change the topic of this discussion into: "Problem with WGM13 in Tinkercad" as your problem is not with Arduino nor the code itself.

2 Likes

Nifty little gadget there =)

Yes, I use it a lot as most of my projects have to do with some form of RC. No more testing with real servo's which often require their own powersource, and I can see the frequency or plain wrong pulses right away.

It is based on a super simple PCB that piggybacks straight on a 1602 display

But the prototype was done with a one dollar STM8S breakout board.

I will change it, thanks for the observations.

What is the type number of your Servo Motor -- is it SG-90 (Fig-1)?
image
Figure-1:

I think so, tinkercad doesn’t offer me details of the servo motor name/serial number, but the problem is that at the 1 << WGM13 tinkercad freeze and I don’t understand why

Do you have a UNO or NANO and a SG-90 type Servo Motor? If yes, then I can provide you two different kinds of sketches -- Servo.h Library based and Registers based.