Kirjautuminen

Haku

Tehtävät

Keskustelu: Yleinen keskustelu: PIC16F84A + rs232 + servo-ohjaus

Turatzuro [23.05.2005 13:52:28]

#

En tiedä onko oikea paikka kysyä asiaa, mutta luulisin että täältä vähintään pari PICceihin perehtynyttä neroa löytyy.

Eli tuollaista hitec hs-300-servoa yritän ohjailla PIC16F84A-piirillä (XT 4Mhz). Sain jo servo-ohjauksen toimimaan hienosti (ajastukset oli pirun vaikeita saada oikein). Nyt pitäisi saada servoa kontrolloitua tietokoneelta, ja ajattelin sitten toteuttaa tiedonsiirron tietokoneelta picille rs232:lla. Picciä ohjelmoin C:llä (kääntäjänä CCS).

Eli löytyisiköhän mistään esimerkkejä tuollaisesta toteutuksesta? Neuvoja otetaan vastaan, kun itseltä on vähän ideat lopussa. Jossain muuten mainittiin, että piiri MAX232 kannattaa lykätä picin ja tietokoneen välille. Mitäs tuo piiri sitten oikeastaan tekee, ilmeisesti jonkinlainen puskuri?

Aijjuu, ja tietokoneessa käyttiksenä toimii Gentoo Linux, eli löytyisikö jostain simppeleitä ohjeita sarjaportin käyttämiseen C:llä linuxissa? Googletus tuotti vain pari melko monimutkaista esimerkkiä...

Juu, tulipa taas kasa kymysyksiä. Toivottavasti täällä on joku joka osaa vastata :S

ajv [23.05.2005 16:42:03]

#

Itellä on ainakin joitakin C-koodeja, joilla olen lpt-porttia ohjaillut. Äkkiseltään voisin kuvitella, että samat koodit pystyisivät myös sarjaporttiin kirjoittamaan, kunhan vaan vaihtaa osoitteen oikeaksi. Itellä on juuri rakenteilla PIC-ohjelmointilaite ja tarkoitus olisi alkaa rakentelemaan sillä kaikennäköistä kivaa, kunhan nyt pääsee kunnolla alkuun...

peran [23.05.2005 18:19:15]

#

Google auttaneen, mutta voinhan joitakin linkkejä yrittää antaa.
http://www.electronic-engineering.ch/microchip/index.html

Täältä modulit, niin on joku RS232 - moduli PICille.

Jos on ongelmia ollut ajoitusten kanssa, niin RS232:n kanssa niitä myös tulee varmasti, ja oskiloskooppi on tarpeen.
PICillä joudut lähettämään bitti kerrallaan RS:ään ja oikeaan aikaan.
Noiden modulien toimminnasta ei ole kokemusta, mutta onhan edes jotain apua, jos niillä on kerran saatu RS toimimaan.
MAX232:sta tarvitaan siksi että PIC-käyttää 5v:ttia ja RS232 12 v, joten sitä tarvitaan siltana.

Veikkaan että Linuxissa pystyy lähettämään RS:ään laiteosoituksella. Eli ohjelma.e >COM1
Tolla tavalla ei ohjelmasta tarvitse tehdä monimutkaista vaan lähettää data vain out:lla tai printf:llä. Lisäksi joudut tosin jostain vääntämään Baudit oikeiksi.

Käsittääkseni 16F873-7, piireissä on parempi yhteensopivuus RS:ään kuin 16F84:ssä, mutta niissäkin joutuu käyttämään MAX232:sta tai jotain muuta viritystä jännitteiden takia.

Turatzuro [24.05.2005 19:41:32]

#

ajv >> Jeps, on noi Picit aika olevia. Itselläni on tuollainen mikrobitissä neuvottu PicProm, jokseenkin näppärä vehjas muuten, mutta prommattavien piccien määrä on jokseenkin rajoitettu :S

peran >> Jeps, nyt onnistuin löytämään jonkilaista apua googlellakin. Muuten hyvä linkki, mutta assemblyä en vielä osaa, vaikkakin taitaapa olla hyvä sekin pikkuhiljaa opetella :S

Nyt sain tuon 16F84A:n lähettämään kamaa jo tietokoneelle (kirjaimia telnetillä), joka oli suhteellisen simppeli homma. Tosin arvaan, että tavaran vastaanotto picillä on sitten jo astetta hankalampaa.

Oskilloskooppia en omista, ja tuskin tulen lähiaikoina omistamaankaan rahanpuutteen takia :( MpLabista löytyi kuitenkin kätevä ominaisuus, jolla voi laskeskella koodin viiveitä yms. sopiviksi, joten josko tällä onnistuisi.

Hyllystä sattui löytymään 16F874A, jossa näyttää olevan oma keskeytyksensä sarjaliikenteelle. Täytyypä siis testata tällä.

RS232:n kanssa olin siinä uskossa, että sen 1-signaali olisi +5v ja 0-signaali 0v, mutta näemmä erehdyin. On se hyvä, etten ehtinyt tökkäämään kaapelia suoraan kiinni picciin :P Ehkäpä pitää tulevaisuudessa vaivautua lukemaan datasheetit paremmin :)

Kiitos vastauksista, eiköhän tällä päästä jo hetken matkaa eteenpäin.

zacura [24.05.2005 19:46:18]

#

Sarjaportin kanssa on muutenkin hyvä käyttää puskuripiiriä, esim. mikrobitin projekteistakin tuttu MAX232 tai MAX238 picin ja pcn välissä muuttamassa signaalit sopiviksi.

Turatzuro [27.05.2005 12:57:42]

#

Sen verran vielä herättelen tätä muutaman päivän vanhaa aihetta, että laitan toimivan ccs:llä kääntyvän servo-ohjauskoodini tänne. Oli _hieman_ hankala saada ajastukset kohdalleen, että toivottavasti joku arvostaa :P

Yhden servon ohjaushan olisi huomattavasti helpompi toteuttaa kuin kahden. Kahden servon toteutuksessa joudutaan ohjaamaan niitä "multitaskaamalla", ja sehän ei picillä onnistu. Sen takia toteutin homman suorittamalla toisen servon komentoja toisen servon taukoaikana. Tässä on ongelmana muuten se, että jos kummankin servon linjat nostetaan tai lasketaan samaan aikaan, kummatkin servot nyppäävät hetkeksi muuttuneen pulssin takia.

Itse annan sarjakaapeliin dataa minicomilla, ja sama homma onnistuu linuxissa myös komennolla

echo x > /dev/ttyS0

(laite riippuen tietenkin sarjaportista).
Tällöin on tosin hankalampaa saada vastaanotettua picin lähettämät viestit. Sarjaportin voi muuten konffata linuxissa esimerkiksi stty:llä. Itse käytän kahta servoa ohjaamaan weppikameraa x- ja y-akseleilla.

Vielä varoituksen sana: Ajastukset voivat olla, ja ovatkin, paskamaisia. Parempi olisi omistaa oskilloskooppi :S Seuraava koodi on tarkoitettu 16F87x-piireille. Toimii ainakin Hitecin HS-300-servojen kanssa.

#include <16F874.h>
#include <stdio.h>
#device adc=8
#use delay(clock=4000000)
#fuses NOWDT,XT, NOPROTECT, NOLVP
#use fast_io(B)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)

// Määritellään vakioita ja makrot
#define A_ALAS output_low(PIN_B7);
#define A_YLOS output_high(PIN_B7);
#define B_ALAS output_low(PIN_B6);
#define B_YLOS output_high(PIN_B6);

#define PAUSE 16000
#define A_TOP 1750
#define A_BOT 550
#define B_TOP 1750
#define B_BOT 550

// Aloitustauot (keskitys)
long kulma = 1000; // 1,2ms wait
long kulmab = 1000;

// Pidetyt tauot
long suora = 0;
long suorb = 0;

int suoritettu = 0;

#int_RDA // Sarjaporttiin kamaa -> keskeytys
void RDA_isr(void) {
	int c;
	c = getc(); // Haetaan sarjaportilta kirjain (ASCII)

	if(c == 120 && kulma < A_TOP) { // Käännetään oikealle, mikäli raja ei ole tullut vastaan
		kulma = kulma + 50;
		puts("RIGHT");
	}
	else if(c == 122 && kulma > A_BOT) { // Käännetään vasemmalle
		kulma = kulma - 50;
		puts("LEFT");
	}
	else if(c == 120 || c == 122) { // Servo jo tapissa
		puts("XLIMIT");
	}

	if(c == 113 && kulmab < B_TOP) { // Kakkos-servoa oikealle
		kulmab = kulmab + 50;
		puts("UP");
	}
	else if(c == 97 && kulmab > B_BOT) { // Kakkos-servoa vasemmalle
		kulmab = kulmab - 50;
		puts("DOWN");
	}
	else if(c == 97 || c == 113) { // Servo jo tapissa
		puts("YLIMIT");
	}
}

void main()
{
	// Hieman asetuksia, turhat ominaisuudet pois päältä
	setup_adc_ports(NO_ANALOGS);
	setup_adc(ADC_OFF);
	setup_psp(PSP_DISABLED);
	setup_spi(FALSE);
	setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
	setup_timer_1(T1_DISABLED);
	setup_timer_2(T2_DISABLED,0,1);
	enable_interrupts(INT_RDA);   // Receive data - keskeytys (HW UART)
	enable_interrupts(GLOBAL);

	// Turhat portit ulostuloiksi
	set_tris_a(0x00);
	set_tris_b(0x00);
	set_tris_d(0x00);

	// Määritetään aluksi kummankin servon pinnit alas
	A_ALAS
	B_ALAS

	while(1) // Pääsilmukka
	{
		if(suora == PAUSE) { // Mikäli annettu 20ms 0-signaalia, nostetaan A-pinni ylös
			A_YLOS
			delay_us(4);
			suoritettu = 1;
		}
		if(suorb == PAUSE) { // Mikäli annettu 20ms 0-signaalia, nostetaan B-pinni ylös
			B_YLOS
			delay_us(4);
			suoritettu = 1;
		}
		if(suora >= PAUSE + kulma) { // Jos A-Pinniä pidetty tarpeeksi kauan ylhäällä, lasketaan se.
			A_ALAS
			suora = 0;
			suoritettu = 1;
		}
		if(suorb >= PAUSE + kulmab) { // Jos B-Pinniä pidetty tarpeeksi kauan ylhäällä, lasketaan se.
			B_ALAS
			suorb = 0;
			suoritettu = 1;
		}

		if(suoritettu == 0) delay_us(10); // pieni tauko, jottei servo nypi
		else suoritettu = 0;

		suora = suora + 50; // Lisätään muuttujiin 50us pidetty tauko
		suorb = suorb + 50;
	}
}

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta