BasCom verfügt ja schon über eingebaute I2C-Befehle. Eigentlich feine Sache.
Kann man damit irgendwie einen Controller als Slave betreiben so das er von anderm Controller per I2C angesprochen wird? Ich suche ein paar Beispiele.
Druckbare Version
BasCom verfügt ja schon über eingebaute I2C-Befehle. Eigentlich feine Sache.
Kann man damit irgendwie einen Controller als Slave betreiben so das er von anderm Controller per I2C angesprochen wird? Ich suche ein paar Beispiele.
Beim Ultraschallsensor SFR04 und SFR08, sowie dem Kompass CMPS03 werden PICs für die Auswertung und Aufbereitung der Sensordaten verwendet. Diese sind über den I2C-Bus (als Slave) auslesbar.
Mit Code kann ich leider nicht dienen.
Ich hab einige Zeilen gefunden
Code:'
' SLAVE-Adresse 100
' nur Daten empfangen möglich/erforderlich --> MASTER-WRITE
' 5 Servos
' Im Feld Daten wird die Nr. des Servo's und dessen Laufrichtung verschlüsselt übergeben
'
'******************************************
Servo1 Alias Portb.1
Servo2 Alias Portb.2
Servo3 Alias Portb.3
Servo4 Alias Portb.4
Servo5 Alias Portb.5
Dim Daten As Byte
Dim I As Byte
$baud = 9600
On Int0 Ext_int0
On Ovf0 Tim0_ovf
Goto Reset
$asm
;***************************************************************************
;* Refers to the application note AVR302 documentation for more
;* detailed description.
;*
;* USAGE
;* Insert user code in the two locations marked "insert user code here".
;*
;* NOTES
;* Minimum one instruction will be executed between each interrupt.
;*
;* STATISTICS
;* Code Size : 160
;* Register Usage : 5 High, 0 Low
;* Interrupt Usage : EXT_INT0 and TIM0_OVF
;* Port Usage : PD4(T0) and PD2(INT0)
;* XTAL : - I2C Fast Mode : min 16.0MHz
;* - I2C Standard Mode : min 3.0MHz
;*
;***************************************************************************
;**** Includes ****
.include "2313def.inc"
;**** Global I2C Constants ****
;.def Devadr = 0x50 ; Slave Device Address geändert
;.def Devadrm = 0x7f ; Slave Multi Address Mask geändert
;.def Pinmaskx = 0x14 ; <=>(1 << Pd4) +(1 << Pd2) geändert
;**** Global Register Variables ****
.def Temp = R16 ; Temporary Variable
.def Etemp = R17 ; Extra Temporary Variable
.def I2cdata = R18 ; I2c Data Register
.def I2cadr = R19 ; I2c Address And Direction Register
.def I2cstat = R20 ; I2c Temporary Sreg Storage
;**** Interrupt Vectors ****
; Anpassung wegen Umstellung von 1200 auf 2313 !!!
; rjmp RESET ;Reset handle
; rjmp EXT_INT0 ;INT0 handle
; rjmp Xxx ;int_1 eingefügt
; rjmp Xxx ;time1_capt eingefügt
; rjmp xxx ;time1_compa eingefügt
; rjmp xxx ;time1_compb eingefügt
; Rjmp Xxx ;Time1_ovfl eingefügt
; rjmp TIM0_OVF ;Timer 0 overflow handle
;
; ( rjmp ANA_COMP ) ; ( Analog comparator handle )
;
;Xxx:
;***************************************************************************
;*
;* INTERRUPT
;* EXT_INT0 / i2c_wakeup
;*
;* DESCRIPTION
;* Detects the start condition and handles the data transfer on
;* the I2C bus.
;*
;* Received data is stored in the r0 register and r0 is transmitted
;* during a master read transfer.
;*
;* NOTE
;* This interrupt code, in some cases, jumps to code parts in the
;* TIM0_OVF / i2c_skip section to reduce code size.
;*
;***************************************************************************
Ext_int0:
in i2cstat,SREG ; store SREG
;*************************
;* Get I2C Slave Address *
;*************************
I2c_get_adr:
ldi i2cadr,1 ; initialize address register
Wlo_ga0:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ga0
rjmp first_ga
Do_ga:
; Do
Wlo_ga:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ga
mov temp,i2cadr ; test address
;orginal andi temp,Devadrm ; mask register full floating bit
andi R16,0x7f ;geändert
;orginal cpi temp,devadr ; if device addressed
;*****************************************************************************
;*****************************************************************************
cpi R16,0x32 ;dig.Adresse (RR&Co) = 100 geändert
;0x32 = binär 0110010 + 0 (R/W-Bit)
;100 = binär 01100100
;*****************************************************************************
;*****************************************************************************
in temp,SREG ; set T flag ("T = Z")
bst temp,1
First_ga:
sec ; set carry
Whi_ga:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_ga
sbis PIND,PIND2 ; if SDA low
clc ; clear carry
rol i2cadr ; shift carry into address register
brcc do_ga ; while register not full
Wlo_ca:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ca
;**** Check Address ****
; if T flag set (device addressed)
brts i2c_adr_ack ; acknowledge address
; else
rjmp i2c_adr_miss ; goto address miss handle
;**** Acknowledge Address ****
I2c_adr_ack:
sbi DDRD,DDD2 ; assert acknowledge on SDA
Whi_aa:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_aa
;**** Check Transfer Direction ****
lsr i2cadr ; if master write
brcc i2c_master_write; goto master write handle
;*******************************
;* Transmit Data (master read) *
;*******************************
I2c_master_read:
;**** Load Data (handle outgoing data) ****
;!INSERT USER CODE HERE !
;!NOTE! If the user code is more than ONE instruction then wait
; states MUST be inserted as shown in description.
mov i2cdata,r0 ; insert data in "serial"
; register (user code example)
sec ; shift MSB out and "floating empty flag" in
rol i2cdata
Wlo_mr:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr
;**** Transmitt data ****
brcc fb_low_mr ; if current data bit high
cbi DDRD,DDD2 ; release SDA
rjmp fb_mr ; goto read loop
Fb_low_mr:
; Else
sbi DDRD,DDD2 ; force SDA
Fb_mr:
Lsl I2cdata ; If Data Register Not Empty
Loop_mr:
Whi_mr:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mr
Wlo_mr2:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr2
brcc b_low_mr ; if current data bit high
cbi DDRD,DDD2 ; release SDA
lsl i2cdata ; if data register not empty
brne loop_mr ; loop
rjmp done_mr ; done
B_low_mr:
; Else
sbi DDRD,DDD2 ; force SDA
lsl i2cdata ; if data register not empty
brne loop_mr ; loop
Done_mr:
Whi_mr2:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mr2
Wlo_mr3:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr3
cbi DDRD,DDD2 ; release SDA
;**** Read Acknowledge from Master ****
Whi_ra:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_ra
sec ; read acknowledge
sbis PIND,PIND2
clc
brcc i2c_master_read ; if ack transfer (next) data
Wlo_ra:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ra
rjmp i2c_wait_cond ; goto wait condition (rep. start or stop)
;*******************************
;* Receive Data (master write) *
;*******************************
I2c_master_write:
Wlo_mw0:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mw0
cbi DDRD,DDD2 ; remove acknowledge from SDA
Whi_mw:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mw
in temp,PIND ; sample SDA (first bit) and SCL
;orginal: andi temp,pinmask
andi R16,0x14 ; mask out SDA and SCL geändert
Do_mw:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask
andi R17,0x14 ; mask out SDA and SCL geändert
cp etemp,temp
breq do_mw ; while no change
sbrs etemp,PIND4 ; if SCL changed to low
rjmp receive_data ; goto receive data
sbrs etemp,PIND2 ; if SDA changed to low
rjmp i2c_get_adr ; goto repeated start
; else
rjmp i2c_stop ; goto transfer stop
Receive_data:
ldi i2cdata,2 ; set i2cdata MSB to zero
sbrc temp,PIND2 ; if SDA sample is one
ldi i2cdata,3 ; set i2cdata MSB to one
Do_rd:
; Do
Wlo_rd:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_rd
sec ; set carry
Whi_rd:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_rd
sbis PIND,PIND2 ; if SDA low
clc ; clear carry
rol i2cdata ; shift carry into data register
brcc do_rd ; while register not full
;**** Acknowledge Data ****
I2c_dat_ack:
Wlo_da:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_da
sbi DDRD,DDD2 ; assert acknowledge on SDA
Whi_da:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_da
; (acknowledge is removed later)
;**** Store Data (handle incoming data) ****
; insert wait states here if nessesary
Sbi Ddrd , Ddd4 ;(start Wait State) aktiviert
;!INSERT USER CODE HERE !
;!NOTE! If the user code is more than TWO instruction then wait
; states MUST be inserted as shown in description.
mov r0,i2cdata ; Store data receved in "serial"
; register (user code example)
Gosub Bearbeitung
cbi DDRD,DDD4 ; (end wait state) aktiviert
cbi DDRD,DDD2 ; remove acknowledge from SDA
;Rjmp I2c_master_write ; Start On Next Transfer geändert / nur Datenempfang
rjmp I2c_stop
;***************************************************************************
;*
;* INTERRUPT
;* TIM0_OVF / i2c_skip
;*
;* DESCRIPTION
;* This interrupt handles a "address miss". If the slave device is
;* not addressed by a master, it will not acknowledge the address.
;*
;* Instead of waiting for a new start condition in a "busy loop"
;* the slave set up the counter to count 8 falling edges on SCL and
;* returns from the current interrupt. This "skipping" of data
;* do not occupies any processor time. When 8 egdes are counted, a
;* timer overflow interrupt handling routine (this one) will check
;* the next condition that accure. If it 's a stop condition
;* the transfer ends, if it 's a repeated start condition a jump
;* to the i2c_wakeup interrupt will read the new address. If a new
;* transfer is initiated the "skipping" process is repeated.
;*
;***************************************************************************
Tim0_ovf:
; (timer 0 Overflow Handle )
in i2cstat,SREG ; store SREG
I2c_adr_miss:
;**** Drop Acknowledge ****
Whi_dac:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_dac
Wlo_dac:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_dac
; disable timer 0 overflow interrupt
;orginal: ldi temp,(0<<TOIE0)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Timsk , Temp
; enable external interrupt request 0
;orginal: ldi temp,(1<<INT0)
clr temp ; eingefügt
sbr temp,&b01000000 ; geändert
Out Gimsk , Temp
;************************
;* Wait for a Condition *
;************************
I2c_wait_cond:
Whi_wc:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_wc
in temp,PIND ; sample SDA (first bit) and SCL
;orginal:andi temp,pinmask ; mask out SDA and SCL
andi R16,0x14 ; geändert
Do_wc:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask ; mask out SDA and SCL
andi R17,0x14 ; geändert
cp etemp,temp
breq do_wc ; while no change
sbrs etemp,PIND4 ; if SCL changed to low
rjmp i2c_skip_byte ; goto skip byte
sbrs etemp,PIND2 ; if SDA changed to low
rjmp i2c_get_adr ; goto repeated start
; else
; goto transfer stop
;*************************
;* Handle Stop Condition *
;*************************
I2c_stop:
;! Set INT0 to generate an interrupt on low level,
;! then set INT0 to generate an interrupt on falling edge.
;! This will clear the EXT_INT0 request flag.
;orginal: ldi temp,(0<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Mcucr , Temp
;orginal: ldi temp,(1<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Mcucr , Temp
Out Sreg , I2cstat ; Restore Sreg
reti ; return from interrupt
;****************
;* Skip byte(s) *
;****************
I2c_skip_byte:
; set counter initial value
ldi temp,-7
Out Tcnt0 , Temp
; enable timer 0 overflow interrupt
;orginal: ldi temp,(1<<TOIE0)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Timsk , Temp
; disable external interrupt request 0
;orginal: ldi temp,(0<<INT0)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Gimsk , Temp
Out Sreg , I2cstat ; Restore Sreg
reti
;***************************************************************************
;*
;* FUNCTION
;* i2c_init
;*
;* DESCRIPTION
;* Initialization of interrupts and port used by the I2C interface
;* and waits for the first start condition.
;*
;* USAGE
;* Jump to this code directly after a reset.
;*
;* RETURN
;* none
;*
;* NOTE
;* Code size can be reduced by 12 instructions (words) if no transfer
;* is started on the I2C bus (bus free), before the interrupt
;* initialization is finished. If this can be ensured, remove the
;* "Wait for I2C Start Condition" part and replace it with a "sei"
;* instruction.
;*
;***************************************************************************
Reset:
I2c_init:
;**** PORT Initialization ****
; Initialize PD2 (INT0) for open colector operation (SDA in/out)
;orginal: ldi temp,(0<<DDD4)+(0<<DDD2)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Ddrd , Temp
; Initialize PD4 (T0) for open colector operation (SCL in/out)
;orginal: ldi temp,(0<<PD4)+(0<<PD2)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Portd , Temp
;**** Interrupt Initialization ****
; Set INT0 to generate an interrupt on falling edge
;orginal: ldi temp,(1<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Mcucr , Temp
; Enable INT0 -> Freigeben INT0 !!!
clr temp
sbr temp,&b01000000 ;setzt bit 6 des Reg. Gimsk ( = INT0) auf 1 / on
Out Gimsk , Temp
; Set clock to count on falling edge of T0
;orginal: ldi temp,(1<<CS02)+(1<<CS01)+(0<< CS00)
clr temp ; eingefügt
sbr temp,&b00000110 ; geändert
Out Tccr0 , Temp
;***************************************************
;* Wait for I2C Start Condition (13 intstructions) *
;***************************************************
Do_start_w:
; Do
in temp,PIND ; sample SDA & SCL
com temp ; invert
;orginal: andi temp,pinmask ; mask SDA and SCL
andi R16,0x14 ; geändert
brne do_start_w ; while (!(SDA && SCL))
in temp,PIND ; sample SDA & SCL
;orginal: andi temp,pinmask ; mask out SDA and SCL
andi R16,0x14 ; geändert
Do_start_w2:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask ; mask out SDA and SCL
andi R17,0x14 ; geändert
cp etemp,temp
breq do_start_w2 ; while no change
sbrc etemp,PIND2 ; if SDA no changed to low
rjmp do_start_w ; repeat
rcall i2c_get_adr ; call(!) interrupt handle (New transfer)
;***************************************************************************
;*
;* PROGRAM
;* main - Test of I2C slave implementation
;*
;***************************************************************************
Main:
Rjmp Main ; Loop Forever
;**** End of File ****
$end Asm
Bearbeitung:
Daten = Peek(0)
Config Portb = Output
Portb = &B11111111 'alle LED aus
If Daten = 1 Or Daten = 11 Then Gosub Servo_1
If Daten = 2 Or Daten = 12 Then Gosub Servo_2
If Daten = 3 Or Daten = 13 Then Gosub Servo_3
If Daten = 4 Or Daten = 14 Then Gosub Servo_4
If Daten = 5 Or Daten = 15 Then Gosub Servo_5
Return
Servo_1:
If Daten = 11 Then Goto Servo_1_links
'-----------------------------------------------
Servo_1_rechts:
For I = 1 To 18 'nach rechts
Portb.1 = 0
Waitms 20
Portb.1 = 1
Waitms 1
Next I
Portb.1 = 0
Return
Servo_1_links:
For I = 1 To 18 'nach links
Portb.1 = 1
Waitms 20
Portb.1 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_2:
If Daten = 12 Then Goto Servo_2_links
For I = 1 To 18 'nach rechts
Portb.2 = 0
Waitms 20
Portb.2 = 1
Waitms 1
Next I
Portb.2 = 0
Return
Servo_2_links:
For I = 1 To 18 'nach links
Portb.2 = 1
Waitms 20
Portb.2 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_3:
If Daten = 13 Then Goto Servo_3_links
For I = 1 To 18 'nach rechts
Portb.3 = 0
Waitms 20
Portb.3 = 1
Waitms 1
Next I
Portb.3 = 0
Return
Servo_3_links:
For I = 1 To 18 'nach links
Portb.3 = 1
Waitms 20
Portb.3 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_4:
If Daten = 14 Then Goto Servo_4_links
For I = 1 To 18 'nach rechts
Portb.4 = 0
Waitms 20
Portb.4 = 1
Waitms 1
Next I
Portb.4 = 0
Return
Servo_4_links:
For I = 1 To 18 'nach links
Portb.4 = 1
Waitms 20
Portb.4 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_5:
If Daten = 15 Then Goto Servo_5_links
For I = 1 To 18 'nach rechts
Portb.5 = 0
Waitms 20
Portb.5 = 1
Waitms 1
Next I
Portb.5 = 0
Return
Servo_5_links:
For I = 1 To 18 'nach links
Portb.5 = 1
Waitms 20
Portb.5 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Irgendwie hilft mir dieser Quelltext beim I2C-Bus nicht sonderlich weiter.
1. Kann das Programm nur ein PWM-Signal für die Maximalausschläge machen? Also lässt sich keine Position sondern nur eine Richtung angeben und die tatsächliche Servoposition muss gemessen und dann das Servo in die richtige Richtung gedreht werden? Wozu dann ein Co-Controller?
2. Zu den I2C-Befehlen: Wie ist das mit denen, die Bascom schon hat? Brauch ich diesen Assebler-Kram trotzdem? Eingentlich will ich nur einzelne Werte übertragen und an einem anderen µC empfangen.
Wenn Du Controller als Slave benutzen willst dann kommst du an Assembler nicht ganz vorbei. Außer du nimmst die I2C-Slave Libary (5 Euro) vom Bascom-Hersteller.
Wenn es um Servos geht, dann kannst Du ja nun Kjions Servo-Programm in den Atmel Controller 90S2313 laden (im Download Bereich). Zum Beispiel beim Board RNBFRA (ich glaub das hast Du ja). Momentan kann dieser allerdings nicht mit Bascom I2C-Befehlen angesteuert werden da Kjions Software noch nicht die volle I2C Bus-Geschwindigkeit unterstützt (soll aber später noch optimiert werden). Ich hab aber eine kleine Engine geschrieben die neue I2C-Befehle, Servo-Befehl, Port-Befehle etc. für RNBFRA beinhaltet. Ist noch nicht ganz fertig weil ich derzeit selten dazu komme. Werde aber in Kürze schon mal die erste Version posten. Man kann dann einfach per Include die Datei in sein Basic Programm einbinden und kann dann alle wichtigen Funktionen des RNBFRA-Boards bequem per Basic-Subroutine steuern und muß nicht als mit den I2C-Befehlen hantieren. Das schreiben von Programmen wird dann noch ne ganze Ecke einfacher
Gruß Frank
Erstmal danke, Frank: Die Bascom-Befehle sind also nur zum Senden...
Einen 90S2313, der Servos stellen kann, hab' ich mir schon gebastelt (ne, ähm das RNBFRA-Board hab' ich nicht, sondern 'nen Eigenbau).
Ich würde jetzt gern die gewünschte Servostellung (insgesamt ca. 10byte für die maximal vorgesehene Anzahl) von einer anderen Quelle entgegennehmen.
Was ist mit dem Befehl "I2creceive" von Bascom? Kann ich dem Empfänger nicht über einen Interupt oder so mitteilen, dass es neue Werte gibt und der empfängt die dann (oder der Servo-AVR "fragt" regelmäßig bei dem anderen die neuen Werte ab?)? Oder geht der Befehl auch nur mit der extra-Library?
PS: Wie lange dauert so ein Zyklus dann (die Servos sind ja solange ohne Ansteuerung.)?
Kann ich das PWM Signal innerhalb eines Modulationsintervalls einfach abbrechen(zum Empfangen der neuen Stellung und dann neu senden) oder ändert das noch die Stellung, wenn der letzte Pulz zu kurz ist?
Ach ja: Was passiert eigentlich, wenn während des Sendens mit Bascom-I2C-Befehl ein Interupt 'reinkommt?
Hi,
ja sicher man könnte Baustein über einen Port ode IRQ darauf aufmerksam machen das es neue Servodaten gibt und er die quasi als Master abrufen soll. Aber dann hättest du ja das Problem mit dem anderen COntroller - denn der müsste nu als Slave programmiert werden :-) Außerdem wäre es Murks :-) wenn ich es mal so sagen darf.
Nö ich würde baustein dann schon vernünftig als Slave programmieren, entweder mit der genannten Libary die du für 5 Euro bekommst oder halt mit oberer Assembler Routine (die hab ich aber nicht ausprobiert).
Das heißt der Hauptcontroller spricht den Servobaustein per I2C an und überträgt ihm die neuen Servo Positionen. Die IC2 Libary nutzt dazu auch einen Interruptfähigen Eingang als I2C-Port.
Ein Problem besteht dann darin das vermutlich deine Servosteuerung kurz unterbrochen wird (während der I2C Übertragung). Inwieweit das deine Servosteuerung beeinflußt mußt du selbst wissen, mit der genauen Impulsgenerierung für die Servos hab ich mich nicht beschäftigt. Da kann Kjion sicher was zu sagen, denn er kennt das Problem. Er sperrt Interrupts während der Servo-Signalgenerierung soweit ich mich erinnere. Dadurch ist aber dann die volle I2C Geschwindigkeit nicht mehr möglich (es würden Takte verpaßt werden).
Wozu I2creceive ist weiß ich aus dem stehgreif garnicht. Ich nehme aber an das er die I2C-Grundfunktionen I2CSTART , I2CSTOP , I2CRBYTE
einfach zusammenfaßt und einige Bytes liest. Abrufen und senden von Bytes ist ja als Master möglich.
Das Beispiel hab ich gefunden:
Das gleiche geht auch mit I2CSTART , I2CSTOP , I2CRBYTE .Code:Example
Config Sda = Portb.5
Config Scl = Portb.7
Dim X As Byte , Slave As Byte
X = 0 'reset variable
Slave = &H40 'slave address of a PCF 8574 I/O IC
I2creceive Slave , X 'get the value
Print X 'print it
Hi,
Beliebig, das ist ja das Problem. Es kann ganz schnell sein, aber theoretisch auch einen Takt pro Stunde...Zitat:
PS: Wie lange dauert so ein Zyklus dann (die Servos sind ja solange ohne Ansteuerung.)?
Kann ab und zu funktionieren, in den meisten Fällen werden allerdings die Servos wild umherzucken.Zitat:
Kann ich das PWM Signal innerhalb eines Modulationsintervalls einfach abbrechen(zum Empfangen der neuen Stellung und dann neu senden)
Das würde auf jeden Fall passieren...Zitat:
ändert das noch die Stellung, wenn der letzte Pulz zu kurz ist?
Bei mir ists im Moment so, dass der Empfang der I2C Befehle im Hauptprogramm passiert. Die Servoansteuerung erfolgt über Timerinterrupts im Hintergrund. Das heißt allerdings, dass die Timerinterrupts zu jedem beliebigen Zeitpunkt auftreten können und damit das schöne Timing vermasseln...Zitat:
Ein Problem besteht dann darin das vermutlich deine Servosteuerung kurz unterbrochen wird (während der I2C Übertragung). Inwieweit das deine Servosteuerung beeinflußt mußt du selbst wissen, mit der genauen Impulsgenerierung für die Servos hab ich mich nicht beschäftigt. Da kann Kjion sicher was zu sagen, denn er kennt das Problem. Er sperrt Interrupts während der Servo-Signalgenerierung soweit ich mich erinnere. Dadurch ist aber dann die volle I2C Geschwindigkeit nicht mehr möglich (es würden Takte verpaßt werden).
Ohne die Servoansteuerung funktionierts auch mit vollen Geschwindigkeit ( hab mir zum Testen mal ein kleines I2C Display gebastelt )
Von dem Code der Oben für die Servoansteuerung gepostet wurde hat übrigens noch ein paar größere Fehler:
Die Servos werden nur angesteuert wenn ein Signal empfangen wurde. Das heißt man muss ständig die Positionen neu senden wenn man das Servo irgendwie belasten will. Des weiteren kann man keine Befehle empfangen während die Servos angesteuert werden. Das heißt man muss nach dem Senden eines Befehls erst eine Pause von mindestens 22 ms einhalten...
Als Master ist das ja egal, da man da beliebig viel Zeit zum Senden hat. Ansonsten wird halt die Senderoutine kurz unterbrochen und der Interrupt abgearbeitet...Zitat:
Ach ja: Was passiert eigentlich, wenn während des Sendens mit Bascom-I2C-Befehl ein Interupt 'reinkommt?
MfG Kjion
Als Master ist senden und Empfangen möglich?Zitat:
Abrufen und senden von Bytes ist ja als Master möglich.
Was spricht dann gegen zwei als Master configurierte AVRs?
Der Haupt-AVR löst einen Interupt beim Servobaustein aus, wenn sich die Positionswerte verändert haben. Der macht dann noch sein Signal fertig und unterbricht dann kurz und führt I2CReceive oder I2CRBYTE aus. Der sendende AVR wartet dann einfach so lange, bis das Servosignal auf jeden Fall fertig ist (max. 2ms) und schickt dann die neue Position (wenn der Servo-AVR früher schon versucht zu empfangen, sollte dem das nix machen oder?).
Dass dann ganz kurz garkein Signal zu den Servos kommt, wird denen nix machen (wenn ich die Modellfernsteuerung ausmache, bleiben die ja auch einfach stehen.).