Need help on I/O for Atmega48 C coding

Status
Not open for further replies.
That's a strange behaviour... The motor should spin only when D0=D1=1 and D2=0. At any other case it should stop. If this is not the behaviour, then something else is wrong. Of course it could be improved, but you must be sure first. Did you debug the code?

1) Which breakpoint is hit after reset?
2) Which breakpoint is hit when you connect D2 to ground?

PS: Don't forget the PORTD |= 7; command before while (1), to make the pull up resistors.
 


how do i use the debug with the hardware @@ I thought debug is only for programming in avr studio ? I dont know which breakpoint is hit.. I taken out the pull up resistors command because i wan D2 = 1 to spin.. i also dont understand how come my mcu so weird, just to make the motor turns with inputs shouldnt be that complicated right @@ Any other method to do this ? hmmm, will it be caused by the mode 14 ? should i change the mode ?
 

blackcsc said:
I taken out the pull up resistors command because i wan D2 = 1 to spin..

That explains a lot... The code you originally posted turns the motor if D2 = 0 and not 1.

Do you want to do something simpler? Download this code:


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main(void)
{
  DDRB |= (1<<PB1);
  TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);
  TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS11);
  DDRD = 0x00;
  ICR1 = 9999;
  OCR1A = 0;
  PORTD |= 0x04;  //make D2 pull up
 
  while(1)
  {
    if (PIND & 0x04)  //if D2 pin is unconnected
    {
      OCR1A = 0;
    }
    else  //pin is grounded
    {
      OCR1A = 1520;
    }
  }
  return 0;
}



The scenario is that you don't care for other pins any more, except D2. Leave D2 unconnected and the motor is NOT spinning. Give ground to D2 and the motor starts spinning. When you remove ground again from D2 pin, motor stops spinning. Try that to verify that your PORTD code runs OK. If the PORTD code is OK and still there are problems, then we will figure out what is wrong.


blackcsc said:
how do i use the debug with the hardware @@ I thought debug is only for programming in avr studio ? I dont know which breakpoint is hit..

I don't use AVR Studio a lot. When I do I use AVR Studio 4. Go to Menu bar and then Debug->Select Platform and device and then select JTAGICE mkII (if mkII is already selected, then skip this step). Then Debug->Start Debugging. When you enter the debug mode, click the cursor on OCR1A = 0; line and click F9 (that is place breakpoint). Do the same with OCR1A = 1520; line. Two red spots on the left should appear, which means that breakpoints are placed. Leave D2 pin unconnected and push F5 (run). Where did the code stopped? It should stop to OCR1A = 0; line. Then connect D2 to ground, leave the ground there and press F5 again. This time the code should stop at OCR1A = 1520; line. If that happens, remove breakpoints (again with F9) and press F5 to run, you should have a working code from PORT code point of view.
 


Thanks for the detailed steps on debugging Actually i need D2, D1 and D0 to control the motor, when D0 & D1 is "1", then motor spin and when D0, D1 and D2 is "1" then i turn back to 0.. That is why i need the case to be 0x03 and 0x07 in PortD to set the condition.. Can this rule applied to your code ?
 

blackcsc said:
when D0 & D1 is "1", then motor spin and when D0, D1 and D2 is "1" then i turn back to 0.. That is why i need the case to be 0x03 and 0x07 in PortD to set the condition.. Can this rule applied to your code ?

Sure. Instead of if-else, use your cases as described in posts 12 and 13 and place breakpoints inside cases to see if they will be hit.
 

Sure. Instead of if-else, use your cases as described in posts 12 and 13 and place breakpoints inside cases to see if they will be hit.

u mean using back the same pull up at PD2 |= 0x04 and replace the if else condition with my cases ?
 

blackcsc said:
u mean using back the same pull up at PD2 |= 0x04 and replace the if else condition with my cases ?

PORTD |= 0x07 and yes, replace if - else with the cases. Try to debug efficiently.
 

PORTD |= 0x07 and yes, replace if - else with the cases. Try to debug efficiently.

Hi Alexxx, is it necessary for the pull up ?? I find it weird when i pull out the D1 from GND to 5v, the motor turns, same goes to D2.. Can i just put it this way ?? i only focus on pin D2 like what you had suggested, but instead of GND it to turn the motor, i want it to be HIGH then it'll turn the motor..

int main(void)
{
DDRB |= (1<<PB1); // Set Port B as output
TCCR1A|=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11); //NON Inverted PWM
TCCR1B|=(1<<WGM13)|(1<<WGM12)|(1<<CS11); //Set Prescaler 8
DDRD = 0x00; // Set Port D as input
ICR1 = 9999;
OCR1A = 0;

while(1)
{
if (PIND=0x03)
{
OCR1A = 1520; // 90 Degree
}
else
{
OCR1A = 0;
}
}
return 0;
}
 

if (PIND=0x03) line, means that the motor starts moving when D0=D1=1 and ALL other PORTD pins including D2 is 0. So the motor should spin ONLY when D0=D1=1 and D2=0.

So it is expected from the motor to turn when you give 5V to D1. But not D2. According to your code the motor will spin ONLY when D2=0.


blackcsc said:
instead of GND it to turn the motor, i want it to be HIGH then it'll turn the motor..

Code:
  if (PIND & 0x07)  //if D0=D1=D2=1
  {
    OCR1A = 1520;
  }
  else  //even one of D0, D1, D2 is low
  {
    OCR1A = 0;
  }

I think this is what you are asking, when D0, 1 and 2 qre high, motor is spinning. Else motor stops.

---------- Post added at 12:25 ---------- Previous post was at 12:05 ----------

Also post your circuit to see how you drive inputs.
 


actually my control should b on D1 instead of D2.. but & is the meaning of AND right ? When i simulated it, either D0 D1 = 1 it will turns.. i tried the code below but the motor do not response again.. WHY !!! haix

if (PIND == 0x03)
{
OCR1A = 1520;
}
else
{
OCR1A = 0;
}
 

Sorry blackcsc, I made a mistake at my previous post.

alexxx said:
if (PIND & 0x07) //if D0=D1=D2=1

This is wrong. The right thing to say was:


Code C - [expand]
1
if (PIND & 0x07)  //if D0=1 OR D1=1 OR D2=1



if you needed all D0, D1 and D2 ports to be 1, you should write:


Code C - [expand]
1
if ((PIND & 0x07)==7)  //if D0=1 AND D1=1 AND D2=1




blackcsc said:
When i simulated it, either D0 D1 = 1 it will turns..
According to what you read above, this was an expected behaviour.


blackcsc said:
i tried the code below but the motor do not response again.. WHY !!! haix


Code C - [expand]
1
2
3
4
5
6
7
8
if (PIND == 0x03)
{
  OCR1A = 1520;
}
else
{
  OCR1A = 0;
}


PIND is an 8 bit register. Every bit represents the status of the corresponding pin. LSB = D0 and MSB = D7. So PORTD=0x03 means that PORTD=00000011b, which means that D0=D1=1, AND D2=D3=D4=D5=D6=D7=0. According to the above code, PIND should be 0x03 to start the motor, that is D0=1 AND D1=1 AND all other pins=0. So if one of D0 or D1 is low, motor won't start. If D0 AND D1 are high but another PORTD pin is also high, then motor won't start again. If you need the motor to depend ONLY on D0 and D1, then you should edit your code as follows:


Code C - [expand]
1
2
3
4
5
6
7
8
if ((PIND & 0x03)==3)  //if D0=D1=1
{
  OCR1A = 1520;
}
else  //D0 or D1 or both are low
{
  OCR1A = 0;
}



Hope that helped.
 

hey alexxx, THANK !!! the code should be :

if ((PIND & 0x07)==3) //if D0=D1=1
{
OCR1A = 1520;
}
else //D0 or D1 or D2 both are low
{
OCR1A = 0;
}

remember that my condition include D2 ? D0 & D1 = 1 then it turns, if D0, D1 & D2 = 1 then it turns also.. If i use PIND & 0x03 then my D2 will not be functioning thanks, hope it works when i combine it with others Will let you know the outcome.. But could you explain what is PIND & 0x03 ? D0 or D1 or D2 ?? & is OR ??
 

blackcsc said:
if ((PIND & 0x07)==3) //if D0=D1=1

Not exactly. The exact explanation would be: if D0=D1=1 AND D2=0

What you meant was:

Code:
if ((PIND & 0x03)==3) //[I]if D0=D1=1 (we don't care about D2 anymore)[/I]

About AVR I/O read the datasheet carefully, it is a simple part to understand. In quick words:
DDRX register controls if PORTX pins will be inputs or outputs
PORTX registers controls a) The pull up if pin is input and b) Pins logic level ('0' or '1') if pin is output
PINX register is read only, you read it to discover if a pin has '1' or '0' on it.

After you read AVR ports carefully, take a look at this thread, you will learn a delicate way to handle your AVR Ports in AVR studio, read it from the beggining:
https://www.edaboard.com/threads/218763/#post930071


blackcsc said:
But could you explain what is PIND & 0x03 ? D0 or D1 or D2 ?? & is OR ?

This is bitwise AND, you do it to keep only bit0 and bit1 unchanged, all other bits go to 0. So since you know that all bits except bit0 and bit1 are 0, the possible results could be 0, 1, 2 and 3. If the result is 3 and since we are talking about PIND, then D0 = D1 = 1.


Alex
 


Thanks Alex Appreciate on your help.. I'll try to figure out, any problem i'll come back and seek help from you all, but 1 more thing, i was told that my pwm calculation was incorrect.. can anyone help me out ? Or should i open another post for pwm ? Let say below are my settings..


Code C - [expand]
1
2
3
4
5
8Mhz clock freq with prescaler of 8
I get 50 hz and 20ms circyle then i got ICR1 = 9999
 
Motor datasheet : 1520 is in neutral position // 90 degree ?
what should i get for 0 degree ?



i realize that my OCR1A = 0 is actually 180 degree and not 0..
 

Hi blackcsc!

Anything you'll need about AVR ports manipulation, you can keep asking in this thread. About AVR's PWM related to servo motors, it would be better to open a new thread. In this way it will be easier for other members to get help when reading these threads in the future, but I think that you will also get better help on PWM if you open a new thread.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…