OK, ostao sam duzan da postavim kod.
Code:
/*
* Project name:
LED_Blinking (Simple 'Hello World' project)
* Copyright:
(c) Mikroelektronika, 2010.
* Revision History:
20080930:
- initial release;
* Description:
This is a simple 'Hello World' project. It turns on/off diodes connected to
PORTA, PORTB, PORTC and PORTD.
* Test configuration:
MCU: ATmega16
http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf
dev.board: easyavr6 -
http://www.mikroe.com/eng/prod...1/easyavr6-development-system/
Oscillator: External Clock 08.0000 MHz
Ext. Modules: -
SW: mikroC PRO for AVR
http://www.mikroe.com/eng/products/view/228/mikroc-pro-for-avr/
* NOTES:
- Make sure you turn ON the PORTA, PORTB, PORTC and PORTD LEDs (SW8.1, SW8.2, SW8.3 and SW8.4).
*/
#include <string.h> //vidi za string funkcije u ovoj bibilioteci
#define BUFF_SIZE 70 //40 da probamo sa 70 da bude velicina: 'SLOVOzaSERVO'XXX puta 17 => 4*17=68, plus karakter za kraj i jos nesto==70
char uart_rd;
int res;
unsigned char a[3];
typedef unsigned char byte;
bit t;
byte br_bajta,s,br_bajta2;
//byte output[4];
int output;
//byte dolazni;
int result;
//char SG;
int SG;
byte SG2[2];
byte SG3[2];
const char _THRESHOLD = 20;
char counter;
const int SMTH = 1250; //servo motor treshold
//1250*16 usec=20msec
int smcount; //servo motor count
int j;
volatile long mer_time;
bit brzosporo;
//Pinovi na koje treba povezati odredjene servo motore
sbit ServoGLava at PORTB.B0;
sbit ServoLevaRukaRame at PORTB.B1;
sbit ServoLevaRukaLakat at PORTB.B2;
sbit ServoLevaRukaSaka at PORTB.B3;
sbit ServoDesnaRukaRame at PORTB.B4;
sbit ServoDesnaRukaLakat at PORTB.B5;
sbit ServoDesnaRukaSaka at PORTB.B6;
sbit ServoLevaNoga1 at PORTB.B7; //neka 1 bude u torsu
sbit ServoLevaNoga2 at PORTC.B1;
sbit ServoLevaNoga3 at PORTC.B2;
sbit ServoLevaNoga4 at PORTC.B3;
sbit ServoLevaNoga5 at PORTC.B4;
sbit ServoDesnaNoga1 at PORTC.B5; //neka 1 bude u torsu
sbit ServoDesnaNoga2 at PORTC.B6;
sbit ServoDesnaNoga3 at PORTC.B7;
sbit ServoDesnaNoga4 at PORTD.B0;
sbit ServoDesnaNoga5 at PORTD.B1;
//vrednosti pri kojima se postavlja nizak logicki nivo za zadati servo
volatile char trVrednostiFIServa[7];
volatile int glavafi;
volatile int lrrfi; //LevaRukaRameFaktorIspune
volatile int lrlfi;
volatile int lrsfi;
volatile int drrfi; //DesnaRukaRameFaktorIspune
volatile int drlfi;
volatile int drsfi;
/*
volatile int ln1fi; //LevaNoga1FaktorIspune
volatile int ln2fi;
volatile int ln3fi;
volatile int ln4fi;
volatile int ln5fi;
volatile int dn1fi; //DesnaNoga1FaktorIspune
volatile int dn2fi;
volatile int dn3fi;
volatile int dn4fi;
volatile int dn5fi;
*/
volatile char prijem[BUFF_SIZE];
volatile char brkar;
volatile char stiglaporuka;
//min fi je 34
//maks fi je 115
void initUSARTbyMIKROC();
//void initUSARTbyME( unsigned int );
void initUSARTbyME( unsigned int baud );
void initUC();
void demoBrzinaSM();
void demoBrzinaSM2();
void pocetnaPozicijaSM();
void pocetnaPozicijaSM_NIZ();
void testiranjeUART();
void ServoPosByUART();
void podesiServoPozicije();
void izvucipodatke();
void newline();
void delay_x16us(long dtime)
{
mer_time=dtime;
while(mer_time);
}
void UART1_Data_recive() org IVT_ADDR_USART1__RX
{
char temp;
temp=UDR1;
prijem[brkar]=temp;
brkar++;
prijem[brkar]='\0'; //oznacava da je u pitanju string
if(temp=='!') //to znaci da je stigao string sa ! koji odredjuje kraj korisne informacije
{
stiglaporuka=1;
}
//prijem karaktera na serijski port
}
void Timer1Overflow_ISR() org IVT_ADDR_TIMER1_OVF
{
//Interapt na svakih 16 uS
TCNT1H = 0xff;
TCNT1L = 0x80;
smcount++;
//Kratko pojasnjenje:
//Generisemo interapt svakih 16 usec, kada i povecavamo brojace
//glavni brojac (smcount) koji ujedno i predstavlja jednu periodu rada servo motora
//se resetuje na otp svakih 20 msec
//Pomocu njega odredjujemo faktor ispune odredjenih servo motora
//u smislu da se na pinove postavlja visok logicki nivo na pocetku periode,
//a spusta se na nizak kada se odredjena promenljiva servo motora imau
//vrednost jednaku sa sa glavnim brojacem
/*
for(j=0;j<4;j++)
{
if(smcount>trVrednostiFIServa[j])
{
switch (j)
{
case 0: ServoGLava=0;
break;
case 1: ServoLevaRukaRame=0;
break;
case 2: ServoLevaRukaLakat=0;
break;
case 3: ServoLevaRukaSaka=0;
break;
// case 5:
// break;
// case 6:
// break;
}
}
}
*/
//IMPORTANT
//Saovakvim principom rada interapta, 4 motora su otprilike maxumum za OK rad
//Prelazak na nizak nivo glave
///*
if(smcount>trVrednostiFIServa[0])
{
ServoGLava=0;
}
//*/
///*
//Prelazak na nizak nivo leve ruke
if(smcount>trVrednostiFIServa[1])
{
ServoLevaRukaRame=0;
}
if(smcount>trVrednostiFIServa[2])
{
ServoLevaRukaLakat=0;
}
if(smcount>trVrednostiFIServa[3])
{
ServoLevaRukaSaka=0;
}
//*/
/*
//Prelazak na nizak nivo desne ruke
if(smcount>drrfi)
{
ServoDesnaRukaRame=0;
}
if(smcount>drlfi)
{
ServoDesnaRukaLakat=0;
}
if(smcount>drsfi)
{
ServoDesnaRukaSaka=0;
}
*/
/*
//Prelazak na nizak nivo leve noge
if(smcount>ln1fi)
{
ServoLevaNoga1=0;
}
if(smcount>ln2fi)
{
ServoLevaNoga2=0;
}
if(smcount>ln3fi)
{
ServoLevaNoga3=0;
}
if(smcount>ln4fi)
{
ServoLevaNoga4=0;
}
if(smcount>ln5fi)
{
ServoLevaNoga5=0;
}
//Prelazak na nizak nivo desne noge
if(smcount>dn1fi)
{
ServoDesnaNoga1=0;
}
if(smcount>dn2fi)
{
ServoDesnaNoga2=0;
}
if(smcount>dn3fi)
{
ServoDesnaNoga3=0;
}
if(smcount>dn4fi)
{
ServoDesnaNoga4=0;
}
if(smcount>dn5fi)
{
ServoDesnaNoga5=0;
}
*/
if(smcount>SMTH) //ovde brojac dostize max vrednost, pa dizemo sve na kec na pocetku novog ciklusa
{
smcount=0;
ServoGLava=1;
ServoLevaRukaRame=1;
ServoLevaRukaLakat=1;
ServoLevaRukaSaka=1;
/*
ServoDesnaRukaRame=1;
ServoDesnaRukaLakat=1;
ServoDesnaRukaSaka=1;
*/
/*
ServoLevaNoga1=1;
ServoLevaNoga2=1;
ServoLevaNoga3=1;
ServoLevaNoga4=1;
ServoLevaNoga5=1;
ServoDesnaNoga1=1;
ServoDesnaNoga2=1;
ServoDesnaNoga3=1;
ServoDesnaNoga4=1;
ServoDesnaNoga5=1;
*/
}
if(mer_time>0)
mer_time--;
else
mer_time=0;
}
void main() {
char i;
initUC();
initUSARTbyMIKROC();
//initUSARTbyME(9600);
//pocetnaPozicijaSM();
pocetnaPozicijaSM_NIZ();
/*
SG='@';
t=0;
brzosporo=0;
br_bajta=0;
br_bajta2=1;
*/
stiglaporuka=0;
for(i=0;i<BUFF_SIZE;i++) //petlja za ciscjenje bafera
{
prijem[i]=0;
}
brkar=0;
do {
if(stiglaporuka)
{
stiglaporuka=0;
izvucipodatke();
}
// demoBrzinaSM();
// demoBrzinaSM2();
// testiranjeUART();
// ServoPosByUART();
} while(1); // Endless loop
}
void izvucipodatke()
{
char fims[4]; //faktor ispune motora string
char i;
char fim[7]; //faktor ispune motora
int rbm,trb; //rbm - redni bronj motora; trb - trenutni broj
//pazi (prilikom slanja) da trb ne sme biti veci od 255
char tk; //trebalo bi da bude trenutni karakter
for(i=0;i<7;i++) //7 motora, ima tako da upisujemo 7 vrednosti u niz
//pre iscitavanja podataka iz bafera, upiseu nulu za svaku od 7 vrednosti
{
fim[i]=0;
}
for(i=0;i<BUFF_SIZE;i++) //iscitavamo karakter po karakter iz bafera serijskog "porta"
{
tk=prijem[i];
prijem[i]=0; //optimizacija koda, odmah nakon iscitavanja odg karaktera, ovo postavljamo na nulu
if(isalpha(tk))
{
rbm=tk-'A'; //redni broj motora= (ASCII code trenutnog karaktera)-(ASCII code slova A); tako za A dobijemo 0, za B 1, za C 3, itd.
//UART1_Write('s'); //obavestenje da je stiglo slovo
//UART1_Write(rbm+1+'0'); //provera koje slovo
trb=0; //Posto je stiglo slovo, pripremamo se za prihvat brojeva koji ga slede, te trb "resetujemo"
}
else if(isdigit(tk)) //ispitivanja da le je trenutni karakter broj, i ako jeste:
{
trb*=10; //Zasto mnozim trb, kada je on nula??????
trb+=tk-'0';
fim[rbm]=trb; //Menjamo podatke za koje je stigla nova informacija o servu
//UART1_Write(trb);
}
}
for(i=0;i<7;i++)
{
if (fim[i]>0) //mala zastita kako ne bi prepisao prethodne vrednosti na nesto nepozeljno
//mozda cak da stavim (fim[i]>30 && fim[i]<115)
trVrednostiFIServa[i]=fim[i];
}
/*for(i=0;i<7;i++)
{
UART1_Write('b');
UART1_Write(fim[i]);
}*/
brkar=0;
}
void initUSARTbyMIKROC()
{
UART1_Init(9600); // Initialize UART module at 9600 bps
//Setuj flag koji dozvoljava USART RX interupt
RXCIE1_bit=1;
//Delay_ms(100); // Wait for UART module to stabilize
delay_x16us(6250); //wait for 100msec
PORTD.B5 = ~PORTD.B5;
UART1_Write_Text("Start"); //radi testiranja
delay_x16us(32500);
PORTD.B5 = ~PORTD.B5;
}
void initUC()
{
//MCUSR &= ~(1 << WDRF);
//wdt_disable();
DDRD = 0xFB; // Set direction of PD2 to be input, the rest of PORTD output
PORTD = 0;
DDRB = 0xFF; // Set direction to be output
PORTB = 0;
DDRC=0b11111110; //DAKLE PORTC.B0 MORA OSTATI ULAZ. proveri semu
//na taj pin je vezan KRISTAL
//DDRC = 0xFE; // Set direction to be output
PORTC = 0;
CLKPR = 0x80;
CLKPR = 0x00;
TCNT1H = 0xff;//100us
TCNT1L = 0x80;
SREG_I_bit = 1; // Interrupt enable
TOIE1_bit = 1; // Timer1 overflow interrupt enable
TCCR1B = 1; // Start timer with 8 prescaler
}
void demoBrzinaSM()
{
//PORTD = ~PORTD;
PORTD.B6 = ~PORTD.B6;
glavafi++;
delay_x16us(3750); //1000 --> cekanje od 16 msec
//1250 --> cekanje od 20 msec
if(glavafi>114) //150
{
delay_x16us(31250);
glavafi=35;//10;
//delay_x16us(25600); //~410 msec
delay_x16us(62500); //1000 msec
delay_x16us(62500);
}
}
void demoBrzinaSM2()
{
if (brzosporo==0)
{
glavafi++;
delay_x16us(3750); //1000 --> cekanje od 16 msec
//1250 --> cekanje od 20 msec
if(glavafi>114)
brzosporo=1;
}
if (brzosporo==1)
{
glavafi--;
delay_x16us(10); //1000 --> cekanje od 16 msec
if(glavafi<1)
brzosporo=0;
}
}
void pocetnaPozicijaSM()
{
glavafi=35;//34 je minimalna vrednost koju konta. Sve idpod toga dolazi do ove pozicije, a ako je vec u ovoj onda se mrda
//ServoGLava=1; //logicki visok napon na pin
lrrfi = 45;
//ServoLevaRukaRame = 1;
lrlfi = 55;
//ServoLevaRukaLakat = 1;
lrsfi = 65;
//ServoLevaRukaSaka = 1;
/*
drrfi = 75;
drlfi = 85;
drsfi = 95;
*/
/*
ln1fi = 65;
ln2fi = 75;
ln3fi = 85;
ln4fi = 95;
ln5fi = 105;
dn1fi = 65;
dn2fi = 75;
dn3fi = 85;
dn4fi = 95;
dn5fi = 105;
*/
// smcount=0; //razmisli da li je bolje da ovo stavljas pred DO
}
void pocetnaPozicijaSM_NIZ()
{
trVrednostiFIServa[0]=45;
trVrednostiFIServa[1]=65;
trVrednostiFIServa[2]=85;
trVrednostiFIServa[3]=105;
}
void initUSARTbyME( unsigned int baud )
{
//iz dokumentacije:
PORTD.B5 = ~PORTD.B5;
/* Set baud rate */
UBRR1H = (unsigned char)(baud>>8);
UBRR1L = (unsigned char)baud;
/* Enable receiver and transmitter */
UCSR1B = (1<<RXEN1)|(1<<TXEN1);
/* Set frame format: 8data, 2stop bit */
UCSR1C = (1<<USBS1)|(3<<UCSZ10);
delay_x16us(62500);
PORTD.B5 = ~PORTD.B5;
}
void testiranjeUART()
{
//testiranje uart-a
if (UART1_Data_Ready()) // If data is received,
{
PORTD.B5 = ~PORTD.B5;
//delay_x16us(6250); //cekanje od 100msec
uart_rd = UART1_Read(); // read the received data,
//delay_x16us(6250);
UART1_Write(uart_rd); // and send data via UART
}
}
void ServoPosByUART()
{
//jednostavna verzija
/*
ServoGLava=fim[0];
ServoLevaRukaRame=fim[1];
ServoLevaRukaLakat=fim[2];
ServoLevaRukaSaka=fim[3];
*/
}
void podesiServoPozicije()
{
}
void newline(){
UART1_Write(13); // Carriage Return
UART1_Write(10); // Line Feed
}
Nisam izbacio visak u odnosu na prekid tajmera tj. same teme, mozda nekom zatreba.
Mala napomena najmanji prekid koji se moze generisati je 10usec i tada se moze upravljati samo jednim servom. Sada se prekid desava svakih 16usec i upravlja se sa 7 serva. Tek cu videti da li sa ovim prekidom tajmera mogu izgurati i malo komplikovanije upravljanje servo motorima pomocu serijskog.
Evo ga i mali program koji savrseno funkcionise u sprezi sa gornjim uC (upravlja servo motorima preko serijskog), pisan je u C sharp 2010:
http://www.2shared.com/file/t0...SerialServoComm_13okt2011.html
Hvala svima na pomoci.
Poz.
[Ovu poruku je menjao endre85 dana 13.10.2011. u 19:34 GMT+1]