Controlling DC-Motor from incremental Encoder pulse signals using ATmega88, C code

Thread Starter

hsj17

Joined Jun 21, 2021
1
I have given the following C-Code to test a 60V DC motor with [gear box ratio 16:1 and incremental encoder to see if the code calculates the speed by reading the Pulse signal as feedback for µcontroller from encoder. The µcontroller is ATmega88A-UA. The encoder RE56-3-1000-TI signals 1000 ppr. The DC motor on special occasions needs to be run at 3-4 RPM for specific task. At lower speed such as less than 5V where motor has starting voltage of 1.8V, the software seems to calculating the incorrect speed values. When at low speeds the mode is TCCR1B == 0x02, the speed value is relatively higher ranging from 255 - 1071 at 2V-5V and frequency 751Hz -3.6kHz accordingly.

When the mode is switched to TCCR1B == 0x01, the speed values calculated/observed (by debugging) ranges from 471 - 1140 at 8V - 20V and frequency from 6.2kHz - 17.4kHz.

What I have also observed that the mode TCCR1B keep switching between 0x01 & 0x02 specially at frequency between 2kHz and 4kHz.

Does any one understands what might be the trouble with incorrect value calculations. Is there some sort of timing problem? The speed variable used is an unsigned int. I need your help. There is a great possibility that things might not be well explained. I'll try my best to give right answers. The prodcut links are included in the description. Any kind of help/suggestions would be very much appreciated. Thanks



60V DC motor: https://www.dunkermotoren.com/en/products/brushed-dc-motors/detail/8844501007/
gear box ratio 16:1: https://www.dunkermotoren.com/en/products/gearboxes/detail/8886001051/
Encoder RE56-3-1000 TI: https://www.dunkermotoren.com/en/products/brakes-and-encoders/encoders/detail/8871005210/


C-code:
#include "iom88.h"
#include "main.h"

 unsigned int Test_Speed_low;       //For testing only!!
 unsigned int Test_Speed_1;       //For testing only!!
 unsigned int Test_Speed_2;       //For testing only!!
 unsigned int Test_Value_Timer_2;       //For testing only!!

int main(void)
{
  // 1 rpm    ->    1000 / 60 = 16,6 Pulse/s  -> 1000 / 16,6 = 60,25 ms/Pulse
  // 10 rpm   ->   10000 / 60 = 166  Pulse/s  -> 1000 / 166  = 6,025 ms/Pulse
  // 120 rpm  ->  120000 / 60 = 2000 Pulse/s  -> 1000 / 2000 = 0,5   ms/Pulse
  // 2000 rpm -> 2000000 / 60 = 33333 Pulse/s -> 1000 / 33333 = 0,03 ms/Pulse
  // 8 Mhz -> 0,125 us / Takt
  // Timer1 CLK/8 -> 1 us / Timer cycle -> 65535 * 1 us = 62 ms -> ~ 1 rpm
  // If pulse is faster than 0.5 ms then measure 10 im pulses with
  // Timer1 CLK/1 -> 0,125 us / Timer cycle -> 65535 * 0,125 us = 8192 us = 8 ms
  // 120 rpm  ->  120000 / 60 = 2000 Pulse/s  -> 10 Pulse = 5 ms -> 5000 us / 0,125 us = 40000 Timerticks
  // 2000 rpm -> 2000000 / 60 = 33333 Pulse/s -> 10 Pulse = 0,3 ms -> 300 us / 0,125 us = 2400 Timerticks
      
  PORTB = 0x00;           // No Pullups
  DDRB = 0x03;            // PORTB_Bit0 = 1k3, Bit1 = 0R

  PORTC = 0;
  DDRC = 0x1F;            // Out_0-4 Outputs 47k, 22k, 11k, 5k6, 2k7

  PORTD = 0x20;           // Pull-Up T1 (Bit5)
  DDRD = 0x00;                               
 
  ACSR = 0x80;            // Disable Analog Comparator
  DIDR1 = 0x03;           // Disable input register on AIN0/AIN1
  ADCSRA = 0xC7;          // Clock / 128 slower is not possible, no INT
  ADMUX = 0xC5;           // Int 1,1V Ref, ADC5
  DIDR0 = 0x20;           // Disable input register on ADC5
 
  TCCR0A = 0x02;          // T0 CRC mode
  TCCR0B = 0x06;          // T0 External clock source on falling edge
  OCR0A = 1;              // CRC int after 1 clocktick
  TIMSK0 = 0x02;          // Timer 0 Compare match A int

  TCCR1A = 0x00;          // T1 normal mode
  TCCR1B = 0x02;          // clk/8 source on T1
  TIMSK1 = 0x01;          // Timer 1 Overflow int
  Value_TCCR1B = TCCR1B;
  Value_Timer1 = 60000;
 
  Min_Timer1 = 60000;
  Max_Timer1 = 0;
  Counter_Timer1 = 0;
 
  Test_Speed_1 = 0;       //For testing only!!
  Test_Speed_2 = 0;       //For testing only!!
  Test_Speed_low = 0;       //For testing only!!
 
  EAL = 1;   
    
  while(1)
  {
    if (TCCR1B == 0x02) {
      if (Value_Timer1 <= 500) {   // < 0,5 ms / Pulse
        OCR0A = 8;                 // CRC int after 8 clocktick
        TCNT0 = 0;                // Reset timer 0 value
        TCCR1B = 0;               // stop T1
        TCNT1 = 0;                // Reset timer 1 value
        TCCR1B = 1;               // clk/1 source on T1
        Value_TCCR1B = TCCR1B;
      }
    } else {   
      if (Value_Timer1 > 40000) {  // > 0,5 ms / 10 Pulse     //Slow Mode
        OCR0A = 1;                // CRC int after 1 clocktick
        TCNT0 = 0;                // Reset timer 0 value
        TCCR1B = 0;               // stop T1
        TCNT1 = 0x1FF;
        TCCR1B = 2;               // clk/8 source on T1
        Value_TCCR1B = TCCR1B;
      }
    }
    
    if (Counter_Timer1 > 2) {
     if (Value_Timer1 < Min_Timer1) {
        Min_Timer1 = Value_Timer1;
      }
      if (Value_Timer1 > Max_Timer1) {
        Max_Timer1 = Value_Timer1;
      }
      if (Counter_Timer1 > 1000) {
        Counter_Timer1 = 0;
        Min_Timer1 = 60000;
        Max_Timer1 = 0;
      }
    }     

    if (TCCR1B == 0x02)
    {                     
      //Speed = 60000 / (Value_Timer1 / 10); // 0,1 RPM,  at 60000 uS -> 1 RPM
      
      Test_Value_Timer_2 = (Value_Timer1/10);         //For testing
      Speed = (60000/Test_Value_Timer_2); // 0,1 RPM,  at 60000 uS -> 1 RPM
      Test_Speed_low = Speed;
    }
    else
    {
      if (Value_Timer1 > 10000)
      {
        //Speed = 48000 / (Value_Timer1 / 100); // 1 RPM,  at 5000 uS -> 120 RPM
        
        Test_Value_Timer_2 = (Value_Timer1/100);      //For Testing
        Speed = (48000/Test_Value_Timer_2); // 1 RPM,  at 5000 uS -> 120 RPM
        Test_Speed_1 = Speed;           //For testing only!!
      }
      else
      {
        //Speed = 48000 / (Value_Timer1 / 10);  // 1 RPM,  at 5000 uS -> 120 RPM  ... 120RPM????
        //Speed *= 10;
        
        Test_Value_Timer_2 = (Value_Timer1/10);         //For testing
        Speed = (48000/Test_Value_Timer_2);  // 1 RPM,  at 5000 uS -> 120 RPM
        Speed *= 10;
        Test_Speed_2 = Speed;       //For testing only!!
      }
    }
  }
}

#pragma vector=INT0_vect

__interrupt void INT0_int(void)   
{
}

#pragma vector=INT1_vect

__interrupt void INT1_int(void)   
{
}

#pragma vector=TIMER0_COMPA_vect

__interrupt void TIMER0_COMPA_int(void)
{
  TCCR1B = 0;                   // Timer1 Stop
  Value_Timer1 = TCNT1;
  TCNT1 = 0;                    // Reset timer 1 value
  TCCR1B = Value_TCCR1B;
  Counter_Timer1++;   
  Counter_Int = 1;
}

#pragma vector=TIMER1_OVF_vect

__interrupt void TIMER1_OVF_int(void)
{
 if (Timer1_OVF == 2)           // Speed < 1,0 RPM
 {   
   Speed = 0;
 }
 else
 {
    Timer1_OVF++;
 }
}
 
Top