PIC: Två saker samtidigt?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
XorXaX
Inlägg: 409
Blev medlem: 27 maj 2004, 09:44:16

Inlägg av XorXaX »

Ok, men hur sk jag då initiera INTCON?

Kod: Markera allt

INTCON = %10010000
eller
INTCON = %11000000
Och vad gör egentligen PIE1.5 = 0 ? Jag hittar ingen info någonstans om PIE1. Och när mitt program har tagit om hand av den seriella datan, ska vilken bit i INTCON ska jag nollställa? bit 0 eller 1?

Men då ska jag alltså använda HSERIN på samma ställa som jag nu använder SERIN?

Tack för att ni är så tålmodiga :o

EDIT:
Kan det var amin Visual Basic kod som jag använder för att skicka datan som är knas?

Kod: Markera allt

Private Sub Command1_Click()
    MSComm1.Output = Text1.Text & Text2.Text
End Sub

Private Sub Form_Load()
    MSComm1.CommPort = 3
    MSComm1.Settings = "2400,N,8,1"
    MSComm1.PortOpen = True
End Sub

Private Sub Form_Unload(Cancel As Integer)
    MSComm1.PortOpen = False
End Sub
Text1 och Text2 innehåller ett fyrsifrigt tal som anger var servorna ska hamna.
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

innan du fortsätter med HSERIN måste du vara säker på att datorn skickar ut korrekt data. Verifiera detta genom att använda en vanlig serin i ett testprogram i PICen och debugga, eller något sånt. Annar kan du klia dig i håret för problem som inte finns ens :doh:

Angående PIE1.5

Saxat ur databladet för PIC16F87x

PIE1 Register
(...)
bit 5 RCIE: USART Receive Interrupt Enable bit
1 = Enables the USART receive interrupt
0 = Disables the USART receive interrupt


Jag tycker det låter ytterst relevant iaf.
XorXaX
Inlägg: 409
Blev medlem: 27 maj 2004, 09:44:16

Inlägg av XorXaX »

Men då fingerar den seriella signalen rätt, för jag har ju styrt servorna var för sig genom ett program jag har gjort och då ställer de sig i rätt position...

Men INTCON då? Hur ska jag ställa in det?
XorXaX
Inlägg: 409
Blev medlem: 27 maj 2004, 09:44:16

Inlägg av XorXaX »

Har följande kod:

Kod: Markera allt

    DEFINE OSC 4
    define HSER_RCSTA 90h
    define HSER_BAUD 2400
    define HSER_SPBRG 25
    
    on interrupt goto ReadValue
    INTCON = %11000000
    PIE1.5 = 1
    
    s0_out var PORTB.1
    s1_out var PORTB.2
    servo0 var word
    servo1 var word
         
    servo0 = 1500
    servo1 = 1500
    
    LOW s0_out
    low s1_out
                
    MoveServo:        
        s0_out = 1
        pauseus (servo0)
        s0_out = 0
        
        s1_out = 1
        pauseus (servo1)
        s1_out = 0
        
        pauseus 15000
        
        goto MoveServo
        
    DISABLE
    ReadValue:
        hserin [servo0, servo1]
        INTCON.0 = 0
        INTCON.1 = 0
        resume
    enable
    
    END
Följande händer:
När jag slår på strömmen till PICen ställer sig servorna i rätt position (1500) och står och drar där. När jag sedan skickar en seriell signal från datorn till PICen så rör sig båda servorna 90 grader till vänster, väntar där i en halv sekund och ställer sig sedan i samma läge som den stod i från början (1500) och drar där. Och det spelar inte någon roll vilka värden jag skickar från datorn till PICen, servorna rör sig alltid åt samma håll (90 grader till vänster) för att sedan gå tillbaka.

Någon som kan hjälpa mig?
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

Det skulle kunna vara så att HSERIN-kommadot är korrupt på någon vänster så att programmet hoppar in i interrupt-rutinen när du skickar datan, men den hänger sig där så att servopulserna uteblir och servomotorerna tror att det är en puls på >2ms och ställer sig i ett ändläge. Men ett servo brukar gå åt höger när pulserna är långa (>2ms) :humm:

kommadot "enable" ska placeras ut som en "klammer" runt den kod den ska omfatta. Du bör därför sätta den precis innan din huvudloop börjar och sedan "disable" precis som du har nu. Dessa är nämligen bara tecken till kompilatorn var den ska polla GIE-flaggan.

Kolla vad som händer med dina servo om du ger dem styrpulser med 2ms pulskvot. Går de åt vänster, precis som du beskrev innan, så har jag nog rätt. Annars tål det att tänkas på igen...


Du kan ju även kolla om interrupt-rutinen funkar genom att tända en LED om den kommer dit. Släck den inte direkt igen bara, för då hinner du inte se att den var tänd :wink:
dangraf
Inlägg: 530
Blev medlem: 9 juni 2003, 15:30:56
Ort: göteborg

Inlägg av dangraf »

Det skulle kunna vara så att interrupten kommer medan den väntar de där 1.5milli sekunderna.
testa att stänga av interrupten innan du ger servona sina pulser, o så sätter du på den igen när den är klar.. Du skulle kanske även kunna öka baudraten lite, så att du vet att den väntar på tecken i vöer 20ms?

jag har även ett annat allternativ till kod, om du vill se. jag är inte van vid basic kod, men har skrivit lite psevdokod, som du får översätta om du vill använda den :-)


DEFINE OSC 4
define HSER_RCSTA 90h
define HSER_BAUD 2400
define HSER_SPBRG 25

on interrupt goto ReadValue
INTCON = %11000000


s0_out var PORTB.1
s1_out var PORTB.2
servo0 var word
servo1 var word

servo0 = 1500
servo1 = 1500

LOW s0_out
low s1_out

timer_prescaler = xxxx //ställ prescalern så att timern räknar upp en
gång var 0.1ms => 200 =20ms

PIE1.5 = 1 //det sissta man gör är att sätta igång interruptet, så man
//vet att initieringen blir klar
timer interrupt = 1



trap:
goto trap

DISABLE
ReadValue:
if(timer_interrupt_flag) // timer har slagit över från 0xff till 0x00
{
clear_timer_interrupt_flag
PIE1.5 = 0 //disable usart int

s0_out = 1
pauseus (servo0)
s0_out = 0

s1_out = 1
pauseus (servo1)
s1_out = 0

time = read_timer0() //kollar hur lång tid det hela har tagit
write timer(0xff - 200+ time)



}
if(usart_interrupt_flag)
{
clear_usart_interrupt_flag
hserin [servo0, servo1]
INTCON.0 = 0
INTCON.1 = 0
}
resume
enable

END
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

:doh:

Att jag inte tänkte på det; man kan ju inte använda "långa" basic-kommandon om man tänkt använda basics "interrupt"-funktion. Därför är pauseus 15000 boven i dramat.

dangrafs exempel var bra!
XorXaX
Inlägg: 409
Blev medlem: 27 maj 2004, 09:44:16

Inlägg av XorXaX »

Långa basic-kommandon? Kan du förklara det lite närmare? Men skulle det gå bra med PAUSE 15 då?
Användarvisningsbild
$tiff
Inlägg: 4941
Blev medlem: 31 maj 2003, 19:47:52
Ort: Göteborg
Kontakt:

Inlägg av $tiff »

Basics låtsas-interrupt kan bara behandlas mellan de färdigsydda basickommandona. Om du därför lägger in en pause 15 så kan inte ett interrupt behandlas medans den pausar. Och 15ms för en mikrokontroller är ju en evighet! Närmare bestämt 15000 instruktionscykler för en PIC @ 4MHz. Det är mycket som hinner svepa förbi då...

Serin (både 1 & 2) är ett annat exempel på en "lång" instruktion, eftersom den har massor av pauser i sig. För att ha en chans att få till det bra så ska man ha så korta instruktioner som möjligt. Att upprepa en 150µs pause 100 gånger ger mycket större chans att hinna ta hand om ett interrupt än att ha det som du har det nu.

Men det bästa är fortfarande att skriva interruptrutinen i assembler, då slipper du alla dessa problem. Kan dock vara svårt att förstå sig på som nybörjare.

Men använd dangrafs metod istället så ska det nog flyta på som vatten :wink:
XorXaX
Inlägg: 409
Blev medlem: 27 maj 2004, 09:44:16

Inlägg av XorXaX »

Ja det har du ju rätt i, 15ms är ganska lång tid. Ska pröve det du sa om att köra en pause på 150µs 100 ggr, eller kanske bättre med en pause på 15µs 1000 ggr?

Om inte det fungerar så kör jag dangraf's exempel, och om det inte skulle fungera för jag sätta mig ner och koda assembler. Har dock inte kommit så lång i det, men jag håller på att lära mig. Och om jag inte får i gång det för jag vänta tills jag läser mikroprocessorteknik i vår.
XorXaX
Inlägg: 409
Blev medlem: 27 maj 2004, 09:44:16

Inlägg av XorXaX »

Töntke göra ett försök på dangraf's kod, tror att jag har funderat ut hur den ska fungera. Ett ltiet problem bara, om jag ska prescala ner TMR0 så att den räknar upp en gång var 100µs så måste jag ju prescala den med 10000, och det går ju inte.

Någon som har ett förslag på hur jag ska prescala den?
Skriv svar