Lieber Besucher, herzlich willkommen bei: RCLine Forum. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.
- RCLine Forum
- » Zubehör,...
- » Fernsteuerungen...
- » Jeti Duplex Telemetrie
Zitat
Original von verleihnix
edit: egal welche Parität ich einstell, ich bekomm bei allem was die Box sendet einen Paritätsfehler.
Gruß Christian
Ich würde sagen du hast entweder ein falsches Datenformat, hältst die Timings nicht ein oder hast falsche Pegel.
Meine Vermutung, schlechtes Timing.
Wenn du Zugang zu einem Oszi hast, einfach mal angucken wie so eine Kommunikation aussieht wenn Sensor und Empfänger kommunizieren. Wenn nicht, bau dir einen Soundkartenoszi der ist dafür noch schnell genug.
Prinzipiell ist es so das die Jeti Box bzw. der Empfänger, wenn er mit einem Sensor gekoppelt ist, die Kommunikationsgeschwindigkeit vorgibt. Es hat ziemlich keinen Sinn einen Datenblock auf Verdacht zu senden ohne auf eine Empfangsbestätigung zu warten. Zwischen Empfangsbestätigung und der Aussendung eines neuen Frames muss man natürlich eine Pause vorsehen weil beide Devices erst zwischen Senden und Empfangen umschalten müssen und evtl. noch ein bisschen andere interne Verwaltungsarbeit ansteht.
Keine Regel ohne Ausnahme.
Wenn Empfänger und Sensor nix voneinander wissen senden sie auf den Schnittstellen Datenframes damit die Gegenstelle die Möglichkeit hat das zu erkennen und in den Pausen dazwischen, ja die sind auch hierbei wieder wichtig weil ich ja der Gegenstelle die Möglichkeit einräumen sollte mir zu antworten ohne das die Antwort zerstört wird, mir zu erkennen zu geben, holla, ja, ich höre dir zu.
Wenn die Kommunikation erst mal synchronisiert ist ballern da auch keine Ausgänge mehr aufeinander rum. Noch ein Grund mehr warum beide aufeinander hören sollten.
sanfte Grüße
Quelle: GBO
Quellcode Box
// PORTD0:1 Jeti
// PORTB1 RS Display
// PORTB2 SEL Display
// PORTB3 SDI Display
// PORTB5 SCK Display
// POrTC0 Taster
// POrTC1 Taster
// POrTC2 Taster
// POrTC3 Taster
#define F_CPU 8000000
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#define RS 1
#define SCK 5
#define SDI 3
#define SEL 2
uint8_t Text[35];
uint8_t z=0;
void spi_init(void)
{ DDRB |= (1<<SEL)|(1<<SDI)|(1<<SCK);
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}
void spi_send(uint8_t send)
{ DDRB |= (1<<SEL)|(1<<SDI)|(1<<SCK);
PORTB&=~(1<<SEL);
SPDR = send;
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
while(!(SPSR & (1<<SPIF)));
PORTB|= (1<<SEL);
}
void LCD_CMD (uint8_t send)
{ PORTB&= ~(1<<RS);
DDRB|= (1<<RS);
spi_send(send);
}
void LCD_TXT (uint8_t send)
{ PORTB|= (1<<RS);
spi_send(send);
}
void USART_out (uint8_t send)
{
_delay_ms(3); // Wartezeit bis Tasterantwort
UCSRB=(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)|(0<<RXEN)|(1<<TXEN)|(1<<UCSZ2)|(1<<RXB


UCSRC=(1<<URSEL)|(0<<UMSEL)|(1<<UPM1)|(1<<UPM0)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)|(0<<UCPOL);
UBRRL=51;
DDRD|=(1<<1);
UDR=send;
while (!( UCSRA & (1<<TXC)));
}
void USART_in (void)
{
UCSRA=0;
UCSRB=(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)|(1<<RXEN)|(0<<TXEN)|(1<<UCSZ2)|(0<<RXB


UCSRC=(1<<URSEL)|(0<<UMSEL)|(1<<UPM1)|(1<<UPM0)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)|(0<<UCPOL);
UBRRL=51;
DDRD=0;
PORTD&=~((1<<1)|(1<<0));
}
int main (void)
{ OSCCAL=pgm_read_byte(0x1fff); // Calibrationsbyte schreiben
_delay_ms(100); // kann nicht schaden
spi_init(); // Display initialisieren
LCD_CMD(0x39); // 8bit 2 lines
LCD_CMD(0x1C); // Bias set
LCD_CMD(0x52);
LCD_CMD(0x69);
LCD_CMD(0x74);
LCD_CMD(0x3

LCD_CMD(0x0f);
LCD_CMD(0x01);
LCD_CMD(0x06);
for(;

{ USART_in ();
while ( !( UCSRA & (1<<RXC)) );
if ((UDR==0xFE)&&(!(UCSRB&(1<<RXB

{ for(z=0;z<32;z++)
{ while ( !( UCSRA & (1<<RXC)) );
Text[z]=UDR;
}
while ( !( UCSRA & (1<<RXC)) );
if (UDR==0xFF)
{ LCD_CMD(0x02);
for(z=0;z<16;z++) LCD_TXT(Text[z]);
LCD_CMD(0xc0);
for(z=0;z<16;z++) LCD_TXT(Text[z+16]);
}
PORTC=0x0f;
USART_out(PINC<<4); //Tasterabfrage und Senden
}
}
}
Quellcode Drehzahlmesser mit Ansatz zum MRPM
// Jetibox an USART
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>
#define F_CPU 8000000UL // 8 MHz
volatile uint16_t Mess[9];
uint8_t MessPos=0;
uint8_t temp=0;
uint16_t temp16=0;
uint32_t temp32=0;
uint16_t Motor=0;
uint16_t Rotor=0;
uint8_t Taster=0;
uint8_t Menu=0;
uint8_t Text[32];
// Drehzahlmessung
ISR(TIMER1_CAPT_vect)
{ if ((ICR1-Mess[8])<250) Mess[8]=ICR1;
else
{ DDRB=(1<<2)|(1<<4);
PORTB=(1<<0)|(1<<2);
Mess[MessPos]=ICR1;
Mess[8]=0;
TCNT1=0;
if (++MessPos==

}
}
// Ausfallkontrolle Drehzahlmessung
ISR(TIMER1_OVF_vect)
{ DDRB=(1<<2)|(1<<4);
PORTB=(1<<0)|(1<<2);
Mess[MessPos]=0xffff;
if (++MessPos==

}
void Dezi_Zahl (uint16_t Zahl,uint8_t Pos)
{ if (Zahl<10000) Text[Pos]=' ';
else Text[Pos]=48+(Zahl/10000);
Zahl=Zahl-(abs(Zahl/10000)*10000);
if ((Zahl<1000)&(Text[Pos]==' ')) Text[Pos+1]=' ';
else Text[Pos+1]=48+(Zahl/1000);
Zahl=Zahl-(abs(Zahl/1000)*1000);
if ((Zahl<100)&(Text[Pos+1]==' ')) Text[Pos+2]=' ';
else Text[Pos+2]=48+(Zahl/100);
Zahl=Zahl-(abs(Zahl/100)*100);
if ((Zahl<10)&(Text[Pos+2]==' ')) Text[Pos+3]=' ';
else Text[Pos+3]=48+(Zahl/10);
Text[Pos+4]=48+Zahl-(abs(Zahl/10)*10);
}
// USART 9600,9,O,1 senden
void USART_ini (void)
{
UCSRA=0;
UCSRB=(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)|(0<<RXEN)|(1<<TXEN)|(1<<UCSZ2)|(0<<RXB


UCSRC=(1<<URSEL)|(0<<UMSEL)|(1<<UPM1)|(1<<UPM0)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)|(0<<UCPOL);
UBRRL=51;
DDRD|=(1<<1);
}
// USART 9600,9,O,1 empfangen
void USART_in (void)
{
while (!( UCSRA & (1<<TXC)) );
UCSRB=(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)|(1<<RXEN)|(0<<TXEN)|(1<<UCSZ2)|(0<<RXB


DDRD&= ~(1<<1);
PORTD|=(1<<1);
}
// Textzeichen senden
void USART_TXT( unsigned int data )
{
while (!( UCSRA & (1<<UDRE)) );
UCSRB |= (1<<TXB

UDR = data;
}
// Steuerzeichen senden
void USART_CMD( unsigned int data )
{
while (!( UCSRA & (1<<UDRE)) );
UCSRB &= ~(1<<TXB

UDR = data;
}
// Programmstart, Initialisierung der Hardware
int main (void)
{ OSCCAL=pgm_read_byte(0x1fff);
TCCR1A=0;
TCCR1B=2|(1<<ICES1)|(1<<ICNC1); // CK/8+IC+ICN
TIMSK=(1<<TICIE1)|(1<<TOIE1); // T1-Interupts on
PORTB=(1<<1)|(1<<2);
DDRB=(1<<2)|(1<<4);
sei();
// Hauptschleife
for(;

{
USART_ini();
USART_CMD(0xFE);
for (temp=0;temp<32;temp++) USART_TXT(Text[temp]);
USART_CMD(0xFF);
USART_in ();
_delay_us(200000);
temp=UDR^0xff;
Taster=Taster ^temp;
Taster=(Taster>>4);
Taster=Taster|(temp&0xf0);
// Nutzprogramm :-)
temp32 =(uint32_t)Mess[0]+Mess[1]+Mess[2]+Mess[3]+Mess[4]+Mess[5]+Mess[6]+Mess[7];
Motor=48000000/ temp32;
if (Motor<92) Motor=0;
Rotor=Motor/8.5;
Text[0]='M';
Text[1]='o';
Text[2]='t';
Text[3]='o';
Text[4]='r';
Text[5]=' ';
Dezi_Zahl(Motor*10,6);
Text[11]=' ';
Text[12]='r';
Text[13]='p';
Text[14]='m';
Text[15]=' ';
Text[16]='R';
Text[17]='o';
Text[18]='t';
Text[19]='o';
Text[20]='r';
Text[21]=' ';
Dezi_Zahl(Rotor*10,22);
Text[27]=' ';
Text[28]='r';
Text[29]='p';
Text[30]='m';
Text[31]=' ';
}
}
Quelle: GBO
War nur ein Timingproblem.
Hab nen Timer benutzt, um die Ausgabe ein und auszuschalten.
Kann jetzt ausgeben und die Taster einlesen.
das ist alles:
![]() |
Quellcode |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
while(1) { if(timerflag1) { _delay_ms(1); UCSRB |= (1<<TXEN); //senden einschalten timerflag1=0; uart_send(0xFE,0); uart_sendstring("ich gruesse das RC-Line Forum ",1); uart_send(0xFF,0); UCSRB &= ~(1<<TXEN); } } |
verleihnix.webege.com
Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »verleihnix« (16. April 2010, 13:58)
Benutzerinformationen überspringen
Wohnort: Dresden/Radeberg
Beruf: verantwortungsträger&rechengenie
Tust du das nämlich nicht, sind ja asynchrone Prozesse, gibt es schnell Quark.
Quax dürfte das nicht interessieren weil er praktisch zwangssynchron arbeitet. Das macht mir diese Methode schon wieder symphatisch.

sanfte Grüße
Quelle: GBO
Mrpm
ich hab den MRPM-Sensor für BL-Motoren "fertig". Hier der Code mit den Grundfunktionen. Menüs könnt Ihr gern nachrüsten:-)
Die Motorphase an PD7. Z.Z wird für den AC die interne Rev von 2,5V genutzt. Deshalb einen passenden Spannungsteiler für 3V<Phase<5V vorsehen. Schaltet man eine externe Rev von 1V an PD6 ist über einen Spannungsteiler von 47k/10k ein Betrieb von 2-6S möglich. Dazu die Rev in Software umschalten.
Gruß Sven
![]() |
Quellcode |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
//MRPM-Sensor // PD6 1V REv , dann (0<<ACBG) // PD7= Motorphase // Jetibox an USART // cal nach 0x1fff schreiben! #include <avr/eeprom.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #include <stdlib.h> #include <util/delay.h> #define F_CPU 8000000UL // 8 MHz volatile uint16_t Mess[2]; uint8_t temp=0; uint16_t Motor=0; uint16_t Rotor=0; uint8_t Taster=0; uint8_t Text[32]; // Drehzahlmessung ISR(TIMER1_CAPT_vect) { if ((ICR1-Mess[1])<150) Mess[1]=ICR1; else { DDRB=(1<<2)|(1<<4); PORTB=(1<<0)|(1<<2); TCNT1=0; Mess[1]=0; Mess[0]++; } } void Dezi_Zahl (uint16_t Zahl,uint8_t Pos) { if (Zahl<10000) Text[Pos]=' '; else Text[Pos]=48+(Zahl/10000); Zahl=Zahl-(abs(Zahl/10000)*10000); if ((Zahl<1000)&(Text[Pos]==' ')) Text[Pos+1]=' '; else Text[Pos+1]=48+(Zahl/1000); Zahl=Zahl-(abs(Zahl/1000)*1000); if ((Zahl<100)&(Text[Pos+1]==' ')) Text[Pos+2]=' '; else Text[Pos+2]=48+(Zahl/100); Zahl=Zahl-(abs(Zahl/100)*100); if ((Zahl<10)&(Text[Pos+2]==' ')) Text[Pos+3]=' '; else Text[Pos+3]=48+(Zahl/10); Text[Pos+4]=48+Zahl-(abs(Zahl/10)*10); } // USART 9600,9,O,1 senden void USART_ini (void) { UCSRA=0; UCSRB=(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)|(0<<RXEN)|(1<<TXEN)|(1<<UCSZ2)|(0<<RXB8)|(0<<TXB8); UCSRC=(1<<URSEL)|(0<<UMSEL)|(1<<UPM1)|(1<<UPM0)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)|(0<<UCPOL); UBRRL=51; DDRD|=(1<<1); } // USART 9600,9,O,1 empfangen void USART_in (void) { while (!( UCSRA & (1<<TXC)) ); UCSRB=(0<<RXCIE)|(0<<TXCIE)|(0<<UDRIE)|(1<<RXEN)|(0<<TXEN)|(1<<UCSZ2)|(0<<RXB8)|(0<<TXB8); DDRD&= ~(1<<1); PORTD|=(1<<1); } // Textzeichen senden void USART_TXT( unsigned int data ) { while (!( UCSRA & (1<<UDRE)) ); UCSRB |= (1<<TXB8); UDR = data; } // Steuerzeichen senden void USART_CMD( unsigned int data ) { while (!( UCSRA & (1<<UDRE)) ); UCSRB &= ~(1<<TXB8); UDR = data; } // Programmstart, Initialisierung der Hardware int main (void) { OSCCAL=pgm_read_byte(0x1fff); TCCR1A=0; TCCR1B=2|(1<<ICES1)|(1<<ICNC1); // CK/8+IC+ICN ACSR=(0<<ACBG)|(1<<ACBG)|(1<<ACIC); // AN1 als Input Wenn externe REV an AN0 (0<<ACBG) TIMSK=(1<<TICIE1); // T1-Interupt on PORTB=(1<<1)|(1<<2); DDRB=(1<<2); sei(); // Hauptschleife for(;;) { USART_ini(); USART_CMD(0xFE); for (temp=0;temp<32;temp++) USART_TXT(Text[temp]); USART_CMD(0xFF); USART_in (); Mess[0]=0; _delay_ms(200); temp=UDR^0xff; Taster=Taster ^temp; Taster=(Taster>>4); Taster=Taster|(temp&0xf0); // Nutzprogramm :-) Motor=Mess[0]*100; // hier je nach Motortyp anders rechnen Rotor=Motor/11.5; // hier je nach Getriebe anders rechnen Text[0]='M'; Text[1]='o'; Text[2]='t'; Text[3]='o'; Text[4]='r'; Text[5]=' '; Dezi_Zahl(Motor,6); Text[11]=' '; Text[12]='r'; Text[13]='p'; Text[14]='m'; Text[15]=' '; Text[16]='R'; Text[17]='o'; Text[18]='t'; Text[19]='o'; Text[20]='r'; Text[21]=' '; Dezi_Zahl(Rotor,22); Text[27]=' '; Text[28]='r'; Text[29]='p'; Text[30]='m'; Text[31]=' '; } } |
Jetiboxcode für atxmega
wer schon mit den neuen Xmegas von Atmel arbeitet, kann von mir per pn ein AVR-Studio-4 Projekt bekommen, das im wesentlichen eine Anpassung des weiter oben schon erwähnten Mikrokopter-Codes von Peter "woggle" Mack,
http://svn.mikrokopter.de/ an den atxmega128a1 ist und natürlich auf den Tips in diesem
schönen Thread beruht. Der C-code sollte einigermassen verständlich sein (und vielleicht etwas einfacher lesbar als der Code da oben

Grüße,
Karl
RE: Mrpm
Zitat
Original von sven.stoecker
Die Motorphase an PD7. Z.Z wird für den AC die interne Rev von 2,5V genutzt. Deshalb einen passenden Spannungsteiler für 3V<Phase<5V vorsehen. Schaltet man eine externe Rev von 1V an PD6 ist über einen Spannungsteiler von 47k/10k ein Betrieb von 2-6S möglich. Dazu die Rev in Software umschalten.
Verstehe ich das richtig......
An PD7 ist eine Phase des Brushless über einen Spannungsteiler direkt angeschlossen?
Thomas
Der Trick ist diese Zeile:
if ((ICR1-Mess[1])<150) Mess[1]=ICR1;
Mein Code ist sicher nicht einfach zu lesen und fast immer unkommentiert. Wer die Funktion prozessornahen Code verstehen will sollte die Wirkung jedes Hardware-Bits nachschauen. Musste ich auch :-)
Gruß Sven
Zitat
if ((ICR1-Mess[1])<150) Mess[1]=ICR1;
OK verstehe.
Ist der Capture Wert nicht mindesten 150 Capture Taktzyklen vom vorherigen Capture Wert entfernt, handelt es sich um einen ungültigen Wert und Mess[0] wird nicht hochgezählt. Also der länger andauernde flache Verlauf einer Phase wird erkannt und der PWM verseuchte Teil ignoriert.
Thomas


Man kann wohl davon ausgehen, dass kein BLC mit weniger als 8kHz gepulst wird, die Pulsbreite also höchstens 125µs lang sein wird. Da liegt 150µs schön drüber.
Und einfach, das ist immer was besonderes, wenn's einfach ist.
Eine kapazitive Einkopplung der Phase könnte mehr Unabhängigkeit von der Höhe der Spannungsversorgung bringen.
[Edit]
Eine schwimmende Referenz (Mittelwert des Eingangssignals = RC-Glied) wär glaube ich besser.
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Quax_BLMC« (12. Mai 2010, 22:38)
ich möchte auf der Motorseite mit einem Optokoppler mit entsprechenden Vorwiderstand experimentieren. Gerechnet werden soll der der Vorwidertsand für 25V (6S Lipo) bei maximal erlaubten LED Strom der Koppler-LED.
Von der Theorie her sollte der LED Strom auch noch bei 2S Lipospannung ausreichend sein.
Das PWM Signal wollte ich auf der sekundären Seite mittels RC Kombi ausfiltern. Nun probiere ich es auch mal in Software

Thomas
JetiBox ATMEGA8
ich verfolge das Thema hier mit sehr großem Interesse. Habe beim Proggen meine JeiBox gelöscht. Jetzt sagt der ATMEGA8 nichts mehr. Hab zwar zugriff jedoch kein Programm mehr drin.
Hat jemand die Boxsoftware modifiziert oder schon nachprogrammiert ?
Bräuchte ASM/C oder hex damit die BOX weiterleben kann.
Danke und Gruß
Andreas
ich habe es, Dank Euch, hinbekommen auf der Jetibox mein GPSDaten inkl. Speed und Höhe anzuzeigen. Nun würde ich gerne auch ein bischen Vario Piepser erzeugen. Das Jeti Vario soll ja auch dazu in der Lage sein.
Weiß jemand was ich der Box schicken muss damit der Sender piepst?
Danke!