Ik ben bezig met de besturing voor mijn robot. Ik wil met de 16f690 een h-brug aansturen. In de datasheet staat hoe ik dat moet doen. Ik weet al hoe ik de motor de andere kant laat draaien, dat doe je door CC1CON = %01001100 of CCP1CON = %11001100 te veranderen.

Ik heb nu dit stukje code, de bedoeling hiervan is om de 3 seconden de motor van richting te veranderen.

Device 16F690                ;Gebruik een 16F690 type
Config HS_OSC, CP_OFF, PWRTE_ON, MCLRE_OFF
XTAL 20

Dim Duty As Word

;         76543210
TRISC =   %00000000           ;(0=uitgang, 1=Ingang)

Duty    = 100                 ;Duty van 10%

While 1 = 1
 GoSub  Links                 ;laat de motor linksom draaien
 DelayMS 3000                 ;Doe dat voor 3 seconden
 
 GoSub Rechts                 ;Laat de motor rechtsom draaien
 DelayMS 3000                 ;Doe dat voor 3 seconden
Wend

End

Links:

  CCP1CON = %11001100         ;links instelling
  T2CON   = %00000110	      ;Zet Timer2 aan, Prescale=16
  PR2     = 249               ;Zet PR2 om 1.22 kHz er uit te krijgen.	
  CCP1CON.4 = Duty.0	      ;Zet duty naar de register
  CCP1CON.5 = Duty.1	      ;als een 10-bit word
  CCPR1L = Duty >> 2
Return                        

Rechts: 

  CCP1CON = %01001100         ;rechts instelling
  T2CON   = %00000110	      ;Zet Timer2 aan, Prescale=16	
  PR2     = 249               ;Zet PR2 om 1.22 kHz er uit te krijgen.
  CCP1CON.4 = Duty.0	      ;Zet Duty naar de register
  CCP1CON.5 = Duty.1	      ;als een 10-Bit Word
  CCPR1L = Duty >> 2
Return 

De code werkt niet goed. Hij stuurt de motor alleen naar links en niet naar rechts aan. Ik denk dat het er aan ligt dat ik de TMR2 niet reset. Maar ik weet niet hoe dat moet, ik heb dit al gebrobeert:

  CCP1CON = %00000000
  T2CON  =  %00000000
  TMR2   =  %00000000

Ik heb dat boven GoSub recht, Gusub links gezet maar dat werkt ook niet.

Kan iemand me mischien uitleggen hoe ik dit moet oplossen

Alvast bedankt

Brandon

Geen idee wat er hier gebeurd...


  CCP1CON.4 = Duty.0	      ;Zet Duty naar de register
  CCP1CON.5 = Duty.1	      ;als een 10-Bit Word
  CCPR1L = Duty >> 2

Ik zou gewoon dit doen...


CCP1RL = Duty ; stop de waarde in het pwm register.

Wat het clearen van de timer betreft dit gebeurd normaal automatisch.
Als de registers staan ingesteld voor PWM...

Heb ik de register niet goed ingestelt?

Dat (raar) stukje komt uit de samples voor HPWM
Dit ik de stuk code daarvan.

' Demonstrate Hardware PWM
' Output a 1KHz signal with duty cycle sweeping from 20% to 80% once per second
		
		Device 16F877
		Declare XTAL 4
        
		Dim Duty	As	Word		' Duty cycle value (CCPR1L:CCP1CON<5:4>)
		
		TRISC.2 = 0					' Set PORTC.2 (CCP1) to output
		CCP1CON = %00001100			' Set CCP1 to PWM 
		T2CON = %00000101			' Turn on Timer2, Prescale=4
		PR2 = 249					' Set PR2 to get 1KHz out	
		Duty = 200					' Set duty cycle to 20%
Loop:	CCP1CON.4 = Duty.0			' Store duty to registers as
		CCP1CON.5 = Duty.1			' a 10-bit word
		CCPR1L = Duty >> 2
		Duty = Duty + 10			' Increase duty cycle	
		DelayMS 17					' Delayms 1/60 of second
		If Duty < 800 Then Loop		' Do it again unless 80% duty cycle
		Duty = 200					' Reset to 20% duty cycle
		GoTo Loop					' Do it forever

en het commando HPWM*? Daar hoef je alleen het HPWM-kanaal (1 in dit geval, er is maar 1 HPWM kanaal), duty-cycle, en frequentie in te voeren en de rest gaat vanzelf. Of wil je dat om bepaalde redenen niet gebruiken?

*Daar staat ook een truukje waarmee je met 1 CCP-kanaal een motor 2 kanten op kan laten gaan met HPWM-mogelijkheid.
En als je H-brug een enable heeft kan je de CCP-pin gewoon aan de enable knopen, en met de 2 inputs de richting selecteren

[Bericht gewijzigd door loopycoaster op (14%)]

Dit is mijn schema, zoals u kunt zien heeft mijn schema geen enable.
Wil bij mij ook dat ik maar 1 HPWM kanaal kan bebruiken? Moet ik dan de schema van Beginners(7f) toepassen
Ik wou het zo doen omdat de 16F690 een Full-Bridge PWM mode heeft, en ik dacht dat dat wel makkelijk zou zijn met mijn schema.

hmm...

Ik had de datasheet toen ik mijn vorige post had gestuurd nog niet doorgekeken. nu wel. Volgens mij kan het hardwarematig wel zoals jij zegt.. En als het lukt bespaart het 1 IO, 2 diodes en 2 weerstanden.

Als je dan de gewone CCP, met maar 1 pin, wilt gebruiken:
De CCP zit op PORTC.5, en dan inderdaad met schema 7f (dus een beetje aanpassen voor de 16F690).

Als het kan dan wil ik het hardwarematig doen. Maar heeft u mischien een idee waarom mijn programa het niet doet?
Op blz. 141 van de datasheet staat hoe ik de richting moet omdraaien. Alleen ik niet goed wat ze hier mee bedoelen.

- The modulated outputs (P1B and P1D) are placed
in their inactive state.
- The associated unmodulated outputs (P1A and
P1C) are switched to drive in the opposite
direction.
- PWM modulation resumes at the beginning of the
next period.

edit
Ik heb tussen mijn code wat leds gezet:

Device 16F690                ;Gebruik een 16F690 type
Config HS_OSC, CP_OFF, PWRTE_ON, MCLRE_OFF
XTAL 20
ALL_DIGITAL = TRUE 

Dim Duty As Word
Symbol Led1 = PORTB.7
Symbol Led2 = PORTC.7
Symbol Led3 = PORTB.6

;         76543210
TRISC =   %00000000           ;(0=uitgang, 1=Ingang)

Duty    = 100                 ;Duty van 10%

High Led1                     ;zet alle leds aan
High Led2
High Led3
DelayMS 1000                  ;wacht 1 seconden
            
Low Led1                      ;zet led1 uit

 GoSub  Links                 ;laat de motor linksom draaien
 DelayMS 3000                 ;Doe dat voor 3 seconden

 Low Led2                     ;zet led2 uit
 

 GoSub Rechts                 ;Laat de motor rechtsom draaien
 DelayMS 3000                 ;Doe dat voor 3 seconden
 
 Low Led3                     ;zet led3 uit


Stop

Links:

  CCP1CON = %11001100         ;links instelling
  T2CON   = %00000110	      ;Zet Timer2 aan, Prescale=16
  PR2     = 249               ;Zet PR2 om 1.22 kHz er uit te krijgen.
  CCP1CON.4 = Duty.0	      ;Zet duty naar de register
  CCP1CON.5 = Duty.1   	      ;als een 10-bit word
  CCPR1L = Duty >> 2
Return                        

Rechts: 

  CCP1CON = %01001100         ;rechts instelling
  T2CON   = %00000110	      ;Zet Timer2 aan, Prescale=16	
  PR2     = 249               ;Zet PR2 om 1.22 kHz er uit te krijgen. 
  CCP1CON.4 = Duty.0	      ;Zet Duty naar de register
  CCP1CON.5 = Duty.1 	      ;als een 10-Bit Word
  CCPR1L = Duty >> 2
Return  

Ik heb als h-brug eerst even 4 leds gebruikt om te kijken wat hij doet.
Wat er gebeurt:

  • Licht alle leds op.
  • Led1 gaat uit en laat de leds die voor zorgen dat de motor linksom gaat branden.
  • Laat alle leds weer branden.

Wat ik hier uit kan concluderen is dat hij niet eens naar de gosub Rechts gaat. Maar hoe kan dit.

[Bericht gewijzigd door Brandon op (67%)]

Als ik in de laaste programa de delayms 3000 weg haal onder GoSub links dan behandelt hij dat niet en gaat direct naar GoSub rechts. Led1 en Led2 gaan dan ook uit.
Van te voren gaan alle leds aan behalve die op poort C4, daarna doe hij dat stukje van GoSub rechts en dan gaan weer alle leds aan behalve poort C4.

Probeer eens:

In je code na DUTY = 100....

WHILE 1=1

en dan in plaats van STOP

WEND

neer te zetten, en geen STOP of END meer gebruiken!!!

Groetjes

Roche

Je weet ook dat je in je code geen rekening houd met de overgangsfase tussen geleiden en niet geleiden van je mosfets (veronderstel ik) in je H-brug?, die er uiteindelijk aan komt te hangen ? Je switched tussen links en rechts zonder een kleine pauze ertussen. Beter dat je je CCP1CON veranderd nadat je 1 ms je uitgangen laag gemaakt hebt.

Dit is wel niet de oplossing voor je probleem, maar je moet er wel op letten.

@Nonkel DW: Het dutycycle register is 10 bit, waarvan de 2 LSB in CCP1CON staan en de 8MSB in CCPR1L. Dus eerst zet hij de 2 LSB in CCP1CON op plaats 5 en 4, daarna zet hij de rest in CCPR1L.

[Bericht gewijzigd door AC/DrieC op (19%)]

@Roches: Dat werkt helaas niet.
@AC/DrieC: Ik weet dat ik er geen rekening mee hou, ik wil eerst dat ding aan de praat krijgen.

Omdat ik 2 pic16f690 gebruik om de robot te besturen dacht ik: Deze 2 PIC laat ik besturen door een 16F877A. Mischien als ik de 16F877A de 16F690 laat aansturen dat het dan wel wil.
Ik wil ze met SPI elkaar laten comisiren. Ik heb er al een keer eerder mee gewerkt, namelijk met een 74hc595. Alleen nog niet met 2 PICtjes.
Ik heb nu 2 code's, 1 voor de 16F877A en 1 voor de 16F690.
Alleen het werkt niet, ik denk dat ik de verkeerde pinnen er voor gebruik maar ik weet het niet zeker. Of licht het aan de code?

16F877A

Device 16F877A                ;We gebruiken een 16F877A type
Config  HS_OSC, WDT_OFF, PWRTE_ON, LVP_OFF    
ALL_DIGITAL TRUE              ;Alle ingangen digitaal
XTAL 20
PORTB_PULLUPS On              ;On-chip pull-up weerstanden actief
  

Symbol DTA = PORTC.5
Symbol CLK = PORTC.3
Symbol Toets1 = PORTB.3
Symbol Toets2 = PORTB.4
Symbol Led1 = PORTB.0
Symbol Led2 = PORTB.1
Symbol Led3 = PORTB.2

;        76543210
PORTC = %00000000 ;Alle niveaus van PORTA eerst laag maken
TRISC = %00000000 ;Alle poorten uitgang 


Clear                         ;Wis alle RAM geheugen
DelayMS 100

High Led1
High Led2
High Led3

While 1 = 1

If Toets1 = 0 Then 
  Low Led1
  SHOut DTA , CLK , msbfirst , [ 10 ]
Else 
  High Led1
EndIf

If Toets2 = 0 Then 
  Low Led2
  SHOut DTA , CLK , msbfirst , [ 20 ]
PulsOut latch, 1
  Else High Led2
EndIf

Wend

End

16F690

Device 16F690                ;Gebruik een 16F690 type
Config HS_OSC, CP_OFF, PWRTE_ON, MCLRE_OFF
XTAL 20
ALL_DIGITAL = TRUE            ;Alle ingangen digitaal

Symbol Led1 = PORTC.1
Symbol Led2 = PORTB.7
Symbol Led3 = PORTC.7

 Symbol CLK = PORTB.6 
 Symbol DTA = PORTB.4 
 
;        76543210
PORTC = %00000000 ;Alle niveaus van PORTA eerst laag maken
PORTB = %00000000 ;Alle niveaus van PORTB laag.
TRISC = %00000000 ;Alle poorten uitgang 
TRISB = %01010000 ;Poort B6 en B4 als ingang SPI

Dim Getal As Byte

High Led1
High Led2 
High Led3 

While 1 = 1
SHIn DTA , CLK , msbpre , [Getal]  ' Shiftin msb-first, pre-clock

If Getal = 10 Then
  Low Led1
Else
  High Led1
EndIf

If Getal = 20 Then 
  Low Led2
Else
  High Led2
EndIf

Wend

je kan niet zomaar shout en shin bij elkaar gebruiken.

Shout en shin zijn beiden master-functies, en bij SPI heb je altijd maar 1 master (en een x aantal slaves).

De master produceert als enige de clockpulsen, wat shout en shin dus beiden doen.In jouw vorige ervaring met een PIC en de 74HC595 was de PIC de master en de 74HC595 de slave.

Je zult dus zelf een subroutinetje moeten schrijven waar je de data ontvangt als shin, maar dan zonder clockpulsen te produceren. Ik kan je wel een beetje op weg helpen als je er niet uitkomt..

Oke, dus de code voor de 16f877A is goed.
Voor de 16f690 moet ik even kijken of ik er uit kom.

Oke, ik heb wat gevonden op het internet.

Read_Data:

Low CS           
    Low CLK
    High DTA ' start bit is high
High CS          
    PulsOut CLK,1
High SDO ' for clarity only- read if bit is high     
    PulsOut CLK,1 ' 
Low SDO ' if low then read data register
    PulsOut CLK,1
    data_in = SHIn DTA , CLK , 0 , 8 ' get data byte ' MSB first
Low CS
    PulsOut CLK,1
Return

Wat niet ingesprongen is, die poorten gebruik ik niet in mijn programa of is dat wel nodig?

Zit ik trouwens wel in de goede richting of zit ik hellemaal verkeert?
P.S. gebruik ik de goede poorten van de 2 pic, denk het haast wel.

Zou iemand me mischien op weg helpen? Ik kom er niet echt uit.
Is I2C ook hiervoor geschikt of is dat moeilijker / onhandig.

 ' Receive a byte from the I2C bus and place it into variable VAR1.
 DIM VAR1 as BYTE               ' We'll only read 8-bits
 DIM Address as WORD            ' 16-bit address required
 SYMBOL Control %10100001       ' Target an eeprom
 SYMBOL SDA = PORTC.3           ' Alias the SDA (Data) line
 SYMBOL SCL = PORTC.4           ' Alias the SSL (Clock) line
 Address = 20                   ' Read the value at address 20
 I2Cin SDA, SCL, Control , Address, [ VAR1 ] ' Read the byte from the eeprom

Dit is een stukje code van help voor I2C en over SDA en SCL moet een pull-up weerstand.

Over de zelfgemaakte Shin:

Volgens mij gaat het inderdaad.... de foute kant op. :P
SPI heeft normaalgesproken geen start/stopbits.
Ook is dit stukje programma iets waarmee je iets verzendt (SHOUT dus) en de Clocksignalen worden nog steeds gestuurd.

I²C is net zoals SPI een synchrone communicatiemanier (er zijn clocklijnen die aangeven hoe snel je wilt verzenden), en is dus ongeveer hetzelfde als SPI, maar dan met start/stop/acknowledge-bits.
I²C is dus juist moeilijker.

Kijk eens naar SEROUT/SERIN: http://www.picbasic.nl/huis-automatisering.htm (naar beneden scrollen)

Je vraag ging over HPWM, die stel je zo in. Dit is alleen voor een 16F877, maar je kan zien hoe het moet. Er staat niet veel verklarende text bij, dus ik hoop dat het duidelijk is zo.


Device 16F877                          ; processor type

XTAL 10                                ; crystal 10 Mhz

Config HS_OSC,_                        ; cristal groter dan 4MHz
       WDT_OFF,_                       ; Watchdog Timer Enable uit
       PWRTE_ON,_                      ; Power-up Timer Enable aan
       BODEN_OFF,_                     ; Brown-out Reset Enable uit
       LVP_OFF,_                       ; Low Voltage Programming uit
       CPD_OFF,_                       ; Memory Code Protection uit
       WRTE_ON,_                       ; Program Memory Write Enable aan
       DEBUG_ON,_                      ; In-Circuit Debugger Mode aan
       CP_OFF                          ; Code Protection uit

ALL_DIGITAL true                       ; alle poorten digitaal

Symbol On  = 1                         ; 1 is hoog
Symbol off = 0                         ; 0 is laag

Symbol vrijgave = PORTC.0
Symbol frequentie = 15000

Symbol S_1 = PORTA.0
Symbol S_2 = PORTA.1
                                       
Declare CCP2_PIN PORTC.1               ; pwm 2 op poort C.1
Declare CCP1_PIN PORTC.2

Declare ADIN_RES    = 8                ; resolutie 8 bits      
Declare ADIN_TAD    = frc              ; Set rc osc     
Declare ADIN_STIME  = 50               ; sample tijd 5 
      
Dim potmeter As Byte
Dim waarde As Byte

Clear                                  ; wis geheugen

DelayMS 2000                           ; wacht 2 seconden

        ;76543210
TRISA = %11111111

        ;76543210                      ; hulp regel poort C
TRISC = %00000000                      ; poort C als uitgang

         ;210                          ; hulp regel poort E       
TRISE  = %111                          ; poort E als ingang       
ADCON0 = %100                          ; analooge ingang 7 

start:

    If S_1 = On Then GoTo run
    vrijgave = off
    HPWM 2,0,0
    HPWM 1,0,0
GoTo start

run:

    potmeter = ADIn 7
    waarde = potmeter
    vrijgave = On
    HPWM 2,waarde,frequentie
    HPWM 1,~waarde,frequentie
    If S_2 = On Then GoTo start
GoTo run

End

@loopycoaster: Oke, ik zal me daar even over buigen.

@Lambiek: Mijn idee was om met een 16F877A de twee 16F690 aan te sturen, en die stuurt op zijn beurt de h-brug aan. De probleem die ik daar bij had dat de 16f690 zijn programa niet afliep.

@Moderator: Wilt U mischien mijn titel veranderen in:
16F877A -> 16F690 -> H-Brug

Edit
Ik heb het even geprobeert maar het lukt niet :(
Dit zijn de codes die ik probeer, zit hier een fout in?
16F690
16F877A

[Bericht gewijzigd door Brandon op (32%)]

Ik heb in dit topic even bekeken. En heb het ook uitgeprobeert. Met 2 16f648A werkt het prefect :)
Maar als ik 1 16F648A verandert in een 16F690 dan werkt het weer niet :(
Ik gebruik de 16F648A als zender en de 16F690 als ontvanger.

Deze code gebruik ik als zender

Device 16F648A
Config WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF, HS_OSC ;INTRC_OSC_NOCLKOUT verwijderd
XTAL = 20

HSERIAL_BAUD = 9600
HSERIAL_RCSTA = %10010000
HSERIAL_TXSTA = %00100000
HSERIAL_CLEAR = On

Symbol Led1 = PORTB.4
Symbol Led2 = PORTB.5

High Led1
High Led2

opnieuw:

DelayMS 2000
HRSOut "1"
Low Led1
DelayMS 500
HRSOut "2"
Low Led2
DelayMS 500    
High Led1
High Led2

GoTo opnieuw

En deze code gebruik ik als ontvanger

Device 16F690                ;Gebruik een 16F690 type
Config HS_OSC, CP_OFF, PWRTE_ON, MCLRE_OFF, WDT_OFF
ALL_DIGITAL =  TRUE              ;Alle ingangen digitaal
XTAL          = 20            ;Gebruik een kristal van 20MHz                 

HSERIAL_BAUD = 9600
HSERIAL_RCSTA = %10010000
HSERIAL_TXSTA = %00100000
HSERIAL_CLEAR = On



Dim VAR1 As Byte

Symbol Led1 = PORTC.1
Symbol Led2 = PORTC.2


DelayMS 500
High Led1
High Led2

DelayMS 1000
Low Led1
Low Led2
DelayMS 1000

loop:


VAR1 = HRSin ,{1000, timeout}

 
Select VAR1            ;Deze SELECT lijst bepaalt wat een ontvangen opdracht gaat doen
    Case "1"                   ;Als de waarde '26' is ontvangen van de bus, dan...
      Led1 = ~Led1              ;... de LED aan of uitzetten (togglen)
      Clear VAR1

   Case "2"                  ;Als waarde '120' is ontvangen, dan...
     Led2 = ~Led2             ;... de LED aanzetten (poort een HOOG niveau geven)
     Clear VAR1
     
End Select

timeout:

Clear VAR1

GoTo loop

Ik gebruik poort B2 van de 16F648A als TX en poort B5 van de 16F690 als RX, lijkt me goed toch?

Mag ik dit wel gebruiken bij een 16F690:

HRSin

Alvast bedankt.

Brandon

Ja poort B5 is goed, wat heb je met poort A3 gedaan pin_4, staan alle configs goed, de zelfde XTALLEN en condensators gebruikt.
Kan je controleren of 16F628 wel zend.

De 16f648a die zend wel, als ik er een led op dan knipert de led even als hij zend.
Ik heb met pin A3 niks gedaan, moet daar een weerstand over.
De xtallen en condensators zijn gelijk.

Ik zet meestal 10K naar de plus. Je hebt ook je TRISB = %..... en TRISC = %..... niet gedaan.

Ik heb een 10K naar de plus gedaan en dit stukje bij de 16f690 geplakt:

;        76543210
TRISB = %00100000
TRISC = %00000000

En dit voor de 16F648A

;        76543210
TRISB = %00000000

Maar dit maakt ook niet uit, werkt nog steets niet.
Ik heb de configs toch goed?

Staat je control register wel goed zo.

RCSTA = %10010000 ?
TXSTA = %00100000 ?

Ik heb dat uit de help bestand, dit stukje.
Dus dat lijkt me goed, klopt dit?

Ik weet trouwens zeker dat het niet licht aan de 16f648a omdat ik dat gecontroleert heb met UART tool en Logic tool van PICkit2

 XTAL = 4

 HSERIAL_BAUD = 9600        ' Set baud rate to 9600
 HSERIAL_RCSTA = %10010000  ' Enable serial port and continuous receive
 HSERIAL_TXSTA = %00100000  ' Enable transmit and asynchronous mode 
 HSERIAL_CLEAR = ON         ' Optionally clear the buffer before receiving

 DIM VAR1 AS BYTE

Loop: 

 VAR1 = HRSIn , {1000 , Timeout}  ' Receive a byte serially into VAR1
 PRINT DEC VAR1 , " "       ' Display the byte received
 GOTO Loop                  ' Loop forever
Timeout: 

 CLS
 PRINT "TIMED OUT"    ' Display an error if HRSIn timed out
 STOP