wie kann man mit dem Arduino nano das SUMD Signal lesen?

ta-uli

User
Hallo,
Ich habe kein Glück beim Googeln: Ich möchte gerne das Graupner HOTT-SUMD Signal mit einem Arduino Nano lesen.
Aber es geht meistens um das analoge PPM-Signal, das hilft mir nicht so ganz weiter.
im Netz gibt es ja vieles zum Thema SUMD und Flightcontroller, aber ich hab nichts passendes gefunden, wie man das Signal einlesen kann.

Das SUMD ist ja ein serieller Datenstrom, der über D0/D1 am Nano eingelesen werden muss.

Da das Signal eine Bitrate von 115200 bit/s hat, scheidet die Library Softwareserial aus. Es ist zu langsam, bzw. es ist der dort benötigte Interrupt schon anderweitig genutzt.

Hat jemand Tipps für mich, wie man es über die D0 bzw. D1 Pins machen kann? Ohne in Konflikt mit der USB-seriell-Verbindung zum PC zu geraten, die an den gleichen Pins arbeitet.

LG
Uli
 
Da das Signal eine Bitrate von 115200 bit/s hat, scheidet die Library Softwareserial aus. Es ist zu langsam, bzw. es ist der dort benötigte Interrupt schon anderweitig genutzt.

Hat jemand Tipps für mich, wie man es über die D0 bzw. D1 Pins machen kann?

Hi

Ich denke, das geht nicht, wenn Du auch USB nutzen willst. Der ATMEGA328 hat nun mal nur eine USART Peripherie und die ist per FTDI Chip mit USB verheiratet.
Nimm stattdessen eine bessere MCU (STM32). Da gibt es mehrere USART Schnittstellen im Chip und für USB ist auch schon ein eingebautes Interface vorhanden.
Die Platinchen sind auch nicht wirklich größer als ein Nano und kosten nur 3,5€.

Gruß
Dieter
 

ta-uli

User
Und es klappt doch...

Und es klappt doch...

Tagchen, zusammen.

Erstmal Danke für die Antwort. Aber das hat mir keine Ruhe gelassen.

Und nachdem ich den Knoten im Kopf aufgedröselt habe:


Falls es jemanden interessiert, es funktioniert doch!

Und zwar liegen jeweils ein 1kOhm-Widerstand zwischen D0/D1 und den Anschlüssen zum USB-Chip.
Daher kann man serielle Daten an D0/D1 anschließen, wenn man mit einem Treiberbaustein arbeitet, und das Signal entsprechend niederohmig an koppelt.
Dann werden die Signale vom USB-Chip sozusagen ignoriert.
Das hatte ich nicht gemacht, und der Empfängerausgang hat eine rel. hohe Impedanz ohne nachgeschaltetem Treiber.Deshalb ging es nicht.
Man darf natürlich nicht vergessen, beim Programmieren über USB diesen externen Treiber von den D0/D1 Anschlüssen abzuklemmen.

Jetzt kann ich endlich das SUMD auslesen und über den Nano weiterverarbeiten.
Das hat den Charme, das von der MX-20 alle 12 Kanäle sogar mit einem GR-12L übertragen werden ...:D
Und ich muss nur ein Kabel in den Empfänger stöpseln.
 
Moin

Ich hänge mich da mal rein. Mit Seriellen Zeug hab ich leider bisher wenig am Hut gehabt, und versuche grad mal das SumD in den Nano zu lesen.
Soweit klappt das, bekomme die vier Kanäle auf den SerialMonitor, ab und an komt mal ne Schlang Nullen vorbei. Nur benötige ich ein delay nach dem drittem Byte, was ich bislang nicht kapiere.
Auch mit dem Protokoll passt das irgendwie nicht ganz: https://www.deviationtx.com/media/kunena/attachments/98/HoTT-SUMD-Spec-REV01-12062012-pdf.pdf
Was mache ich falsch ?
Code:
uint8_t Buffer;
int ch1, ch2, ch3, ch4;

void setup() {
Serial.begin(115200);
}

void loop() {
 if (Serial.available()){  Buffer = Serial.read();                //A8
 if (Buffer == 0xA8){      Buffer = Serial.read();                //FF
 if (Buffer == 0xFF){      Buffer = Serial.read();    delay(1);   //FF
                           Buffer = Serial.read();                //01 
                           Buffer = Serial.read();                //0C
                           Buffer = Serial.read();    ch1 = Buffer <<8;  
                           Buffer = Serial.read();    ch1 = ch1 + Buffer; 
                           Buffer = Serial.read();    ch2 = Buffer <<8;
                           Buffer = Serial.read();    ch2 = ch2 + Buffer;
                           Buffer = Serial.read();    ch3 = Buffer <<8;
                           Buffer = Serial.read();    ch3 = ch3 + Buffer;
                           Buffer = Serial.read();    ch4 = Buffer <<8;
                           Buffer = Serial.read();    ch4 = ch4 + Buffer;
                           debug();
}}}
}

void debug(){
Serial.print(ch1 >>3);
Serial.print("  ");
Serial.print(ch2 >>3);
Serial.print("  ");
Serial.print(ch3 >>3);
Serial.print("  ");
Serial.println(ch4 >>3); 
}
 

Ay3.14

User
Wie kann man nur auf die Idee kommen und einen "Arduino Nano" mit dessen USB-Interface für etwas anderes zu verwenden? Macht doch irgendwie keinen Sinn, oder verstehe ich da etwas falsch?
:confused:
Wäre es denn in diesem Fall nicht besser nur einen ATMega328 mit minimaler Beschaltung (ohne USB) zu verwenden?
 

ta-uli

User
Hallo,

der Anschluss des seriellen Eingangs des ATMega ist nicht direkt mit dem Ausgang des USB-Chips verbunden, sondern über einen 1 kOhm-Widerstand.
Also kann man über einen niederohmigen Impedanzwandler das Empfängersignal direkt an den ATMega anschliessen. Damit "überschreibt" man das Signal vom USB-Chip.
Das geht wunderbar. Allerdings muss diese Verbindung abgeklemmt werden, wen man den Nano über den PC programmieren will, oder vom PC Daten zu ihm schicken möchte. Es geht also nicht USB und Empfänger gleichzeitig.

Uli
 
Als Testumgebung auf dem Schreibtisch :)
Die Daten über dem RX kommen ja wunderbar reingelaufen.
 

Ay3.14

User
Aha!

Aha!

Danke für die Info, jetzt habe ich es kapiert!
;)
Ist schon ganz schön trickreich, aber halt nicht gleichzeitig nutzbar.
 

ta-uli

User
Na,
1. bei HOTT überträgt auch ein GR-12 z.B. alle 12 Kanäle der MX-20, obwohl der Empfänger nur 6 Servo-Kanäle hat !
2. Wenn der Arduino die Kanalinfos erst mal hat, kann man ihn als Flight Controller benutzen, wie er in manchen Multicoptern benutzt wird.
3. Steuerung von Zusatzfunktionen: Beleuchtung, bei Schiffen den ganzen Schnickschnack,....
4. man hat Spass dran... :)

Uli
 
Das mag ich garnicht sagen, aus Angst hier erschlagen zu werden :D Ich will die Servos abschalten, wenn der Knüppel grad nicht bewegt wird, um Strom zu sparen im Solarflieger.

Zusätzlich brauche ich den Gaskanal für die MPP-Steuerung.

Im Moment beiße ich mir aber grad die Zähne daran aus, wie man das "Servosignal" (PPM/PWM) auf einem Pin beendet :rolleyes: Mit servo.dettach gibt es miese Störungen, aber das gibt sich schon noch...


EDIT
UND eine kleine Spielerei für die Akkuflieger, die SumD Bytes könnte man so wie sie sind "getarnt" als andere Werte auf die Telemetrie zurückwerfen, und sich dann im Log auf der Sernder-SD-Card anschauen, was man da so fürn Mist zusammenknüppelt:D;)
 

husi

User
Hallo Holger,

Ich will die Servos abschalten, wenn der Knüppel grad nicht bewegt wird, um Strom zu sparen im Solarflieger.
dann gehe ich mal davon aus, das es keine digital-Servos sind, die dann ohne Strom "weich" werden, oder?
Wie findest du die Idee, über einen entsprechend dimensionierten Transistor die Stromleitung der Servos "abzuschalten" bzw. zu unterbrechen? Dann kann das PWM-Signal weiterhin normal an die Servos geliefert werden, trotzdem sind sie "aus".


Und was macht man dann so mit den Kanalinformationen aus dem SUMD-Signal?
Das hätte ich für meine MPX-Anlage auch gerne, um alle Kanäle auf eine SD-Karte zu loggen.
Der nächste Ansatz wäre, auf Grund von Sensoren-Meßwerten z.B. Mischer im Modell an den Flugzustand automatisch anpassen zu lassen.


Viele Grüße
Mirko
 
Hallo Mirko
Ja, das sind selbsthemmende Servos. Digitale würden zuviel Strom verbrauchen, und Glockenankermotoren sind nicht selbsthemmend, wodurch sie auch sonst am Ruderdruck mehr Ruhestrom aufnehmen.
Strom wegschalten habe ich derzeit über einen Schalter am Sender über ein MosFet, es dauert einen klitzekleinen Moment bis sie wieder aufwachen.
Wenn ich den PWM wegschalte geht der Ruhestrom auf ca 2-3mA runter, die Hoffnung war auf weitere Bauteile verzichten zu können.
Im Solarflieger rennt eh schon alles auf 3,3V am Pololu-getaktetem BEC, statt 5V Linear-BEC (von 6,3V runter), Telemetrie ist deaktiviert, Prozessoren auf 8MHz statt 16MHz, u.s.w. hat ca. 1Watt gespart, bei unter 10Watt Eingangsleistung unter einer Wolke ist das sehr viel.
 
Auch wenn es völlig offtopic ist, Servo abschalten funzt schonmal, einfach mit PWM Null anbrüllen, dann erschreckt es sich, und stellt ab ;)
(ich glaub ich müsst noch ein paar mehr Timer einlöten....)
Code:
void setup() {                    
DDRB |=0b00000110;    // D9 is ESC,  D13 is LED
TCCR1A=0b10000010;   // Fast PWM
TCCR1B=0b00010010;   // Fast PWM
ICR1  =20000;         // ICT-Top 20000 für Servos, 2000 für SimonK-ESC. Geregelt jeweils mit 1000-2000(ms)
}

void loop(){
OCR1A = 1500;          // Servo fährt zur Mitte
PORTB |= _BV(PB5);     // LED an
delay(2000);                         

OCR1A = 0000;            // Servo abschalten
PORTB &= ~_BV(PB5);    // LED aus
delay(2000); 
}
 
Zurück zum Thema SUMD

Danke für die beiden Codes per PN :)

Ich habe parallel mal den Code aus der Multi-WII extrahiert. zusätzlich einen Filter, gaaanz selten kommt da sonst auch mal ein "Käsesatz" mit neg. Werten vorbei. Ansonsten rennt der gut, auch direkt stumpf am Nano (chg340)


Code:
int i, channel[4], rcValue[4];
#define SUMD_MAXCHAN 4
#define SUMD_BUFFSIZE SUMD_MAXCHAN*2 + 5 
static uint8_t sumdIndex=0;
static uint8_t sumdSize=0;
static uint8_t sumd[SUMD_BUFFSIZE]={0}; 

void setup(){
Serial.begin(115200);
}

void loop() {
  while (Serial.available()) {
    int val = Serial.read();//Serial.println(val,HEX);
    if(sumdIndex == 0 && val != 0xA8) {continue; }
    if(sumdIndex == 2) {sumdSize = val;}
    if(sumdIndex < SUMD_BUFFSIZE) {sumd[sumdIndex] = val;}
    sumdIndex++;
      
    if(sumdIndex == sumdSize*2+5) 
    { sumdIndex = 0;
      if (sumdSize > SUMD_MAXCHAN) sumdSize = SUMD_MAXCHAN; 
      for (uint8_t b = 0; b < sumdSize; b++){
      rcValue[b] = ((sumd[2*b+3]<<8) | sumd[2*b+4])>>3;
      if (rcValue[b] > 750 && rcValue[b] < 2250){channel[b] = rcValue[b];}  //filter
    }}
  }
  
debug();
}

void debug(){
Serial.print(channel[0]);
Serial.print("  ");
Serial.print(channel[1]);
Serial.print("  ");
Serial.print(channel[2]);
Serial.print("  ");
Serial.print(channel[3]);
Serial.println("  ");
delay(50);
}
 

BOcnc

User
Hallo Holger,

so ganz verstehe ich das nicht.
Ich habe das mal vor ein paar Jahren mit MPX Daten gemacht.
Ich habe mit einem Timer die Lücke zwischen den Paketen gesucht und dadurch den Paketstartpunkt gefunden.
Wenn man das mit den Bytes macht kann die Reihenfolge auch zufällig an anderer Stelle vorkommen.
Ich glaube das ist genau das Problem weshalb das bei dir sporadisch mal nicht funktioniert.

Gruß
Werner
 
Moin Moin

Ich habe es jetzt etwas anders gelöst, gelesen wird im UART Interrupt, das Ganze in C, weil a) lernen:rolleyes: und b) Speicher (die neuen Attinys 102/212/214...) Aktuell brauche ich 300Byte wenn Serialdebug aus ist.
Man könnte nun noch die Checksumme abfragen, es noch etwas weiter "abspecken", aber es rennt schon so sehr stabil, also quasi "Zwischenstand" und Forum als "Zwischenablage" missbraucht ;). Vielleicht kann ja wer was mit anfangen.
Code:
#define F_CPU 16000000
#include <util/delay.h>
#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <stdlib.h>

uint8_t  SUMD[36];
uint16_t channel[13];

//Serialsend deaktivieren ca. -200Byte
char s[7];
void serialsend (char *s){
while (*s){ 
  while (!(UCSR0A & (1<<UDRE0))){}                             
  UDR0 = *s;      
  s++;
}}//*/


int main(void){
UCSR0B |= _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0); 
UBRR0L = 8;   //115200baud/16MHz                                        
sei();

while(1){ 
  
for (int i=1; i <= 7; i++){
  channel[i] = (SUMD[i*2+2]<<5)+(SUMD[i*2+3]>>3);
  serialsend( itoa( channel[i], s, 10 )); serialsend(" ");
}
  serialsend("  \r\n");
}}


ISR(USART_RX_vect){
uint8_t Buffer;
int start;
static uint8_t pos;
Buffer = UDR0; 
SUMD[pos] = UDR0;  
if(Buffer==0xA8){start=1;}
if(Buffer==0x01 && start==1){pos=1;}else{start=0;}
pos++;  
}
 
Ansicht hell / dunkel umschalten
Oben Unten