5

After all there is more question poping up then answers i decide to upload the pdf where is everything writen, like the wire, motor type and what we can and can't use. Here is the link pdf format of the assignment

So i am working on a project for the school, it is first time for me to work with Microcontrollers. I and i got stuck with the rest of my assignment, so i hope a good soul can help me out with this.

So my code for now is this

#include <stdio.h>
#include "dev/uart.h"
#include <util/delay.h>
#include <avr/io.h>
#include "dev/adc.h"

#define LED_RED     (1 << PE5)
#define LED_YELLOW  (1 << PE3)
#define BUTTON      (1 << PF2)
#define SENSOR      (1 << PF3)
#define PUSH        (PINF & (BUTTON))
#define TILT        (!(PINF & (SENSOR)))

#define JOYSTICK_X  (1 << PF0)
#define JOYSTICK_Y  (1 << PF1)

typedef struct 
{
    uint16_t x;
    uint16_t y; 
} inputVector;

typedef struct
{
    int16_t x;
    int16_t y;
} convertedVector;

void joystick_init()
{
    adc_init(0x03);
}

convertedVector joystick_status()
{
    inputVector newVector;
    convertedVector vector;
    newVector.x = adc_get(0);
    newVector.y = adc_get(1);

    inputVector max;
    max.x = 896;
    max.y = 902;

    inputVector min;
    min.x = 8;
    min.y = 9;

    vector.x = 0;
    vector.y = 0;

    if(newVector.x >= 498 && newVector.x <= 518)
    {
        vector.x = 0;
    }
    else if(newVector.x < 498)
    {
        vector.x = ((newVector.x * 100) / 901) - 100;
    }
    else
    {
        int16_t half = 896/2;
        vector.x = ((newVector.x * 50) / half);
    }

    if(newVector.y >= 492 && newVector.y <= 512)
    {
        vector.y = 0;
    }
    else if(newVector.y < 492)
    {
        vector.y = ((newVector.y * 100) / 901) - 100;
    }
    else
    {
        int16_t half = 901/2;
        vector.y = ((newVector.y * 50) / half);
    }

    printf("x: %d, y: %d\n", vector.x, vector.y);

    return vector;
}

int main(void) {
    uart_init(9600);
    //uint8_t counter = 0;

    DDRE |= (LED_RED); /* OUTPUT */
    DDRE |= (LED_YELLOW);

    DDRF &= ~(BUTTON);  /* INPUT */
    DDRF &= ~(SENSOR);  

    /*      JOYSTICK       */
    DDRF &= ~(JOYSTICK_X);  /* INPUT */
    DDRF &= ~(JOYSTICK_Y);
    joystick_init();

    while (1){

        if(!PUSH && !TILT)
        {
            PORTE |= (LED_RED);
            PORTE |= (LED_YELLOW);
            _delay_ms(50);
            PORTE = 0;
            _delay_ms(50);
        }   

        if(PUSH && !TILT)
        {
            PORTE |= (LED_RED);
            _delay_ms(50);
            PORTE = 0;
            _delay_ms(50);
        }   

        if(!PUSH && TILT)
        {
            PORTE |= (LED_YELLOW);
            _delay_ms(50);
            PORTE = 0;
            _delay_ms(50);
        }


        if(PUSH && TILT)
        {
            PORTE |= (LED_RED);
            _delay_ms(500);
            PORTE = 0;

            PORTE |= (LED_YELLOW);
            _delay_ms(500);
            PORTE = 0;
        }

        joystick_status();
        //_delay_ms(100);
    }
    return 0;
}

What it does now it reads the input values from joystick and it can be (x or y) min: 8 and max: 900, but we need to map it to [-100,100] this works but not perfect, so if someone can help to do the mapping better i would be grateful, but that is not the main point of my question.

But my real question is how i can programm the MCU to generate PWM signals ?

I need to implant those 3 functions :

  • servo_init(), to initialize the timer/counter2;
  • servo_left(int v), to set the angular velocity of the left wheel;
  • servo_right(int v), to set the angular velocity of the right wheel;

There are four registers to be set during the initialization: TCCR2A, TCCR2B, OCR2A, OCR2B.So what they mean ?

The two functions servo_le f t(intv) and servo_right(intv) set the corresponding Output Compare Register to control the pulse duration of the output control signal. The input parameter v of each function is an integer in the range [−100, 100] whose absolute value is proportional to the angular velocity of the corresponding servomotor and whose sign defines the direction of rotation. As overall, these functions map the input range [−100, 100] to the output range [1.0, 2.0] ms which corresponds to the pulse duration of the control signal, thus the angular velocity and rotation direction of the servomotor. Notice that, as the two servomotors are symmetrically mounted, one of the two functions has to invert the direction of rotation.

Right wheel : PortB, pin 4, Output Compare Register : OC2A, TinkerKit Conn: O1

Left wheel : PortH, pin 6, Output Compare Register : OC2B, TinkerKit Conn: O2

I spend all day on the internet finding anything that would help out, but i didn't have any luck.

4
  • 1
    It's not wrong, but I just want to confirm something. You are using Arduino right? because your code does not seems like one
    – duck
    Nov 23, 2016 at 1:22
  • You may ask your teacher if it's okay to use the Arduino platform or servo libraries. Possibly it is, possibly he wants you to implement it in a low level fashion.
    – Paul
    Nov 23, 2016 at 7:09
  • Don't cross post on multiple SE sites. Your other question was already put on hold for being off topic, but you asked here before that.
    – gre_gor
    Nov 23, 2016 at 14:07
  • Because i din't know that we have this page.
    – twistedhat
    Nov 23, 2016 at 19:21

2 Answers 2

3

||-----PWM Register Explanation-----||

It will be easier to explain with an example.
Here is a sample of Timer setup on ATMega2560 (assuming that is the one you use due to the tag "Arduino-mega") based on datasheet section 20 : 8-bit Timer/Counter2 with PWM and Asynchronous :Operation:

TCCR2A= 0b10110001; //set COM2A1, COM2B1, COM2B0 and WGM20
TCCR2B= 0b00000001; //set CS20

register description

  • WGM22,WGM21, and WGM20 --> 001 ==> Using Phase correct PWM mode
  • COM2A1, COM2A0 --> 10 ==> Clear OC2A on Compare Match when up-counting, and Set OC2A on Compare Match when down-counting
  • COM2B1, COM2B0 --> 11 ==> Set OC2B on Compare Match when up-counting, and Clear OC2B on Compare Match when down-counting
  • CS22, CS21 and CS 20 --> 001 ==> No clock prescaling

COM2A1, COM2A0 set the Timer2A on non-inverting mode, and COM2B1, COM2B0 set the Timer2B on inverting mode.

OCR2A and OCR2B is the duty cycle value of PWM. Because timer2 is 8 bit, so the value is ranging from 0-255. Its also the answer to your question

How i can program the MCU to generate PWM signals ?

PWM Signal frequency is defined by its duty cycle :

Duty cycle of Timer2x = (OCR2x/255)*100%

for example :

OCR2A = 100;
OCR2B = 155;

Timer2A will work on 39.2% duty cycle and OCR2B will also work on 39.2% duty cycle. What? Because Timer2B works on inverted mode (100%-60.8%) ==> 39.2%

||-----PWM topic closed here-------||

I've seen several people losing several hair while trying to control analog servo without manually (well, some even move to Arduino only because of its servo libs).
You can check this Servo Library which is (maybe) the most common library used to control servo using Arduino (which also mentioned in @st2000 answer).
But, it will be better if you also post a detail about your "motorservo". At first I though it was a motor DC (by its PWM - Dir configuration).

||-----Additional-----------------------||
In your while(1), there are several if that can be optimalized by using simple if-else if-.. statement. So this one would be better (also minimalized "bug" chance) :

while(1)
{
  if(!PUSH && !TILT) 
       {...} else
  if(PUSH && !TILT) 
       {...} else
  if(PUSH && TILT) 
       {...} else
...
...
}    

--EDIT--
After reading several page of the PDF, I assume you have to make your own library (not Arduino). Perhaps this will give you something :

void servo_init(void)
{
 TCCR2A= 0b10110001; 
 TCCR2B= 0b00000001;
 /*phase correct PWM mode,
  *no clock prescaler,
  *Timer2A -> non inverted,
  *Timer2B -> inverted
  */
}

void servo_left(int v)
{
 int convertedvalue =//map angular velocity of left servo into 0-255
 OCR2A = convertedvalue;
}

void servo_right(int v)
{
 int convertedvalue = //map angular velocity of right servo into 0-255
 OCR2B = convertedvalue;

}
4
  • we are using two servomotor's to control the movements of the robot. He goes forward and backwards when the 2 motors have the same velocity and right or left if on has high velocity then other one.
    – twistedhat
    Nov 23, 2016 at 5:19
  • If so, further information about the servomotor is needed. i.e : what is the motor series? do you use driver motor? what about the wiring? You can edit your question with those information so that other user can quickly notice
    – duck
    Nov 23, 2016 at 5:57
  • so i edit the question and post a link to the pdf, because it would be just annoying to type it all
    – twistedhat
    Nov 23, 2016 at 8:29
  • Let us continue this discussion in chat.
    – duck
    Nov 23, 2016 at 9:29
0

Your question is confusing. It appears you are creating code for an Atmel processor which directly interfaces with hardware. Atmel does make some of the processors used in Arduinos. However, all Arduinos abstract the hardware using libraries with very simple APIs. For example, to control a servo motor an application written in the Arduino paradigm only needs to include the servo header file, instantiate an instance of the servo class, call a servo class method to indicate which pin the servo is connected to then call a servo class method with a value equal to the angle the servo motor is to move to:

#include <Servo.h> 

Servo myservo;

void setup() 
{ 
  myservo.attach(9);
  myservo.write(90);  // set servo to mid-point
} 

void loop() {} 

If you decide to switch to the arduino paradigm, the above code should be all you need to control your normal servo motors.

On the other hand, you may be using continuous servo motors. Again, this is confusing because you did not say what type of servos you are using. But it may be that the angle in the above example will actually be interpreted as a speed when dealing with continuous servo motors.

1
  • please see my.comment about the motor above.
    – twistedhat
    Nov 23, 2016 at 5:20

Your Answer

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

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