Communicatie tussen Arduino Uno en atoomkloksignaal ontvanger/decodeer module

buckfast_beekeeper

Golden Member

Het zijn allemaal tekens uit de extended ASCII tabel.

œ is in 7 bits een formfeed.
ü is in 7 bits een | (vertical bar)

Probeer de output eens te monitoren met een Logic Analyzer mocht je die hebben. Je hebt blijkbaar een mogelijkheid een seriële monitor aan te sluiten. Je hebt zelf een programma geschreven in python. Mogelijk is daar een fout ingeslopen. probeer een keer met een terminal programma zoals Putty. Dan kan je op dat vlak fouten uitsluiten.

Van Lambiek wordt goede geuze gemaakt.
Shiptronic

Overleden

Als je geen MAX232 gebruikt, moest je dan niet de signalen inverteren ?

Wie de vraag stelt, zal met het antwoord moeten leren leven.

De module loopt op 300 baud, Transmit naar de module is 8-bit, no parity. Receive vanaf de module is 7 bit even parity.

Dat kun je niet instellen in de meeste uarts. Het gemakkelijkste is de uart in te stellen op 8 bit, no parity. Maar dan krijg je wel het parity bit mee met de ontvangen data. Je kunt die parity gebruiken, maar het is veel gemakkelijker om die eraf te strippen.

De communikatie tussen Arduino en de PC Kan veel sneller. 300 baud is nogal ongebruikelijk daar. Je kunt de instellingen op de PC controleren. En om die link te controleren kun je het beste een bekende string versturen bij opstarten. Dat kan bijvoorbeeld met de volgende setup;

code:


void setup()  
{
  // Open serial communications and wait for port to open:
  // Deze gaat naar de klok. 
  Serial.begin(300, SERIAL_8N1);
 
  // Set the data rate for the SoftwareSerial port
  // En deze naar de PC 
  mySerial.begin(300, SERIAL_8N1);
  
  delay(1000);  

  // Stuur een bekende tekst naar de PC om de communikatie te
  // testen 
  mySerial.println("Goedemiddag");
 
  // Wait for synchronisation with the signal
  delay(180000);
}

In de loop moet je een commando versturen. Maar bij elke byte moet je wachten op de echo. Maar je weet niet zeker of er wel een echo is. Dus om te beginnen gewoon een delay tussen de te versturen bytes. Een char op 300 baud duurt 30 milliseconden en je moet 5 milli extra wachten :

code:


void loop() // run over and over
{
  // Send time protocol command
  Serial.write(0x3F);
  delay(40);           // Delay tussen chars
  Serial.write(0x0D);
  delay(40);           // Delay tussen chars

Vervolgens weet je niet zeker of er iets terugkomt, en wat je terug krijgt. Maar de kans is groot dat je wel even moet wachten voordat het zover is :
Je kunt het beste de klok gebruiken om een maximum tijd te wachten op antwoord:

code:


   // StartTijd registreren   
   unsigned long Time = millis();
   
   while((millis() - Time) < 2000)  //< Max 2 seconden wachten
   {
      if (Serial.available())
      {  //< Lees data van klokmodule en strip parity bit weg 
         char c = (Serial.read() & 0x7F);  

         // Converteer het ontvangen byte naar Hex
         // Zodat we kunnen zien of en wat er binnen komt 
         MySerial.write( "0123456789ABCDEF"[(c & 0x70) >> 4]);
         MySerial.write( "0123456789ABCDEF"[c & 0x0F]);
         MySerial.writeln();    
      }
   }
}

PS code niet getest. Gebruik geheel op eigen risico. Misschien werkt het niet. ;-)

buckfast_beekeeper

Golden Member

Daarom ook best een AVR gebruiken met 2 aparte UART. 1 zet je op 7 bits en de andere op 8 bits.

Wordt X3 constant laag gehouden kan de 2de UART aan een hogere frequentie draaien. Aan de andere kant, heeft dit zin? Als de data niet sneller binnen komt kan je ze ook niet sneller aan de pc aanleveren.

Van Lambiek wordt goede geuze gemaakt.
mel

Golden Member

Op 21 maart 2016 12:20:16 schreef buckfast_beekeeper:wat ik niet uit de handleiding haal, of ik kijk er over, welke tijd wordt er weergegeven? DCF loopt 1 minuut voor. Je ontvangt steeds de gegevens van de volgende minuut. Wordt hier de tot de seconde nauwkeurige realtime uitgezonden?

DCF loopt idd een minuut voor. Er word gebruik gemaakt van de BCD code.De 59 seconde word geen signaal uitgezonden, en daarna is het de eerste seconde van de nieuwe minuut, (die dus als het goed is) in BCD uitgezonden is.

u=ir betekent niet :U bent ingenieur..

Ik heb de code van deKees gebruikt.
De code hieronder is de compileerbare versie ervan.
Het probleem is dat de eerste strings (start sync en stop sync) als volgt worden weergegeven: ~Œ€üŒ ð þ pð´ð || |´€þ´| pð´ð ||
Ik heb nog geen idee hoe dit komt, maar ik zoek dit uit.

Er komt geen data op de monitor te voorschijn. Ik denk dat dit komt door de omzetting naar hex, ben dit ook nog aan het uitzoeken.

Code:

c code:

/*
  Software serial multiple serial test
 
 Receives from the hardware serial, sends to software serial.
 Receives from software serial, sends to hardware serial.
 
 The circuit: 
 * RX is digital pin 10 (connect to TX of other device)
 * TX is digital pin 11 (connect to RX of other device)
 
 created back in the mists of time
 modified 25 May 2012
 by Tom Igoe
 based on Mikal Hart's example
 
 This example code is in the public domain.
 
 */
#include <SoftwareSerial.h>

SoftwareSerial mySerial(11, 10); // RX, TX

void setup()  
{
  // Open serial communications and wait for port to open
  Serial.begin(300);

  // Set the data rate for the PC port
  mySerial.begin(300);
  
  delay(1000);
  
  // Test communication to the PC and syncronize with the signal
  Serial.print("Start sync\n");
  delay(180000);
  Serial.print("Stop sync\n");
}

void loop()
{
  // Send time protocol command
  mySerial.write(0x3F);
  delay(40);
  mySerial.write(0x0D);
  delay(40);
  
  // Receive data
  if (mySerial.available()){
    // Strip down the parity bit
    char c = (mySerial.read() & 0x7F);
    
    // Convert Byte to Hex
    Serial.print("0123456789ABCDEF" [(c & 0x70) >> 4]);
    Serial.print("0123456789ABCDEF" [c & 0x0F]);
    Serial.println("\n");
  }
}
buckfast_beekeeper

Golden Member

Als de omzetting naar hex goed gebeurd, mag dit het probleem niet zijn. 0xFF = 255 = b11111111 de uart heeft geen kennis van hex of oct of wat dan ook. Die krijgt een waarde aangeboden en deze wordt uitgezonden/ontvangen.

Heb je een logic analyzer ter beschikking? Dan kan je de uart lijn een keer monitoren en zien wat er wordt verzonden.

Van Lambiek wordt goede geuze gemaakt.

Beste buckfast_beekeeper

Ik heb geen instrumenten zoals een logic analyzer of oscilloscoop ter beschikking om dit te kunnen nagaan.

Arco

Special Member

Het probleem is dat de eerste strings (start sync en stop sync) als volgt worden weergegeven: ~Œ€üŒ ð þ pð´ð || |´€þ´| pð´ð ||

Dan deugt je terminal programma niet of staat verkeerd ingesteld. Dat zijn extended Ascii characters. In 7 bits mode zou je die helemaal niet kunnen zien.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Ik heb eindelijk nog eens wat tijd gehad om mij hiermee bezig te houden.

Ik heb een zeer simpel programma geschreven om mijn seriële monitor te testen en van hieruit uit te breiden naar de uiteindelijke code.

Ik merk op dat ik helemaal niets te zien krijg dus vraag ik mij af of ik mijn chip heb stuk gekregen of zou er iets anders aan de hand zijn?

c code:


int i;

void setup() {
  // put your setup code here, to run once:
  Serial.print("Start");
  i = 0;
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("loop " + i);
  i++;
  delay(1000);
}

Blijkbaar kan mijn pc de lage baudrate niet aan (300 baud). Ik heb deze verhoogd naar 9600 baud. Vanaf nu krijg ik toch bruikbare data binnen.

'yff& 2&bbfff& 'yff& e2&&bfff y'yf&fbffb&bff& ...

Nu vraag ik mij af wat hier van tijdsbasis zou staan en hoe ik een nieuwe start reeks herken, is het de vele spaties die aanduiden van een nieuwe reeks?

Mvg
Vayneless

Arco

Special Member

Volgens datasheet moet je o <cr> sturen, dan kerijg je de data terug. De module sluit ook met een <cr> af, dus wat daarna komt is nieuw.
Ik zie trouwens niet in hoe dat op 9600 baud kan werken, want dat kan die module helemaal niet...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
buckfast_beekeeper

Golden Member

Wat is er bruikbaar aan "'yff& 2&bbfff& 'yff& e2&&bfff y'yf&fbffb&bff& ..."? Ik verwacht toch eerder iets als "1936451020516".

Als de laptop de 300Bd niet aan kan ga je iets anders moeten verzinnen. Een andere baudrate selecteren op je pc, en de module kan deze niet aan, is geen oplossing. De communicatie moet bij allebei met dezelfde parameters gebeuren.

Heb je al een terminal programma zoals Putty gebruikt?

edit: In elke byte bevatten slechts de 4 LSB de informatie.
byte opbouw
bit 7 = pariteit
bit 6 = altijd 0
bit 5 = altijd 1
bit 4 = altijd 1
bit 3
bit 2
bit 1
bit 0

Zo krijg je 13 van in totaal 15 bytes met
byte 1 = uren tientallen
byte 2 = uren eenheden
byte 3 = minuten tientallen
byte 4 = minuten eenheden
byte 5 = seconden tientallen
byte 6 = seconden eenheden
byte 7 = weekdag (1 = maandag ... 7 = zondag)
byte 8 = datum tientallen
byte 9 = datum eenheden
byte 10 = maand tientallen
byte 11 = maand eenheden
byte 12 = jaar tientallen
byte 13 = jaar eenheden

byte 14 = bits 16...19 van het dcf protocol.
bit 4...7 idem als hier boven aangegeven.
bit 3 = aankondiging schrikkelseconde (bit 19 DCF)
bit 2 = 1 tijdens wintertijd (bit 18 DCF)
bit 1 = 1 tijdens zomertijd (bit 17 DCF)
bit 0 = aankondiging wissel zomer/wintertijd (bit 16 DCF)

byte 15 = status
bit 4.. 7 idem als hierboven.
bit 3 = 1 als batterijspanning te laag.
bit 2 = 1 zo lang er geen geldige tijdsinfo werd ontvangen.
bit 1 = 1 als de voorgaande ontvangstpoging correcte tijdsinfo is ontvangen. 0 als de vorige poging de tijdsinfo niet correct was
bit 0 = 1 als er correcte tijdsinfo ter beschikking is.

[Bericht gewijzigd door buckfast_beekeeper op maandag 2 mei 2016 19:56:39 (60%)

Van Lambiek wordt goede geuze gemaakt.

Dit heeft niets met de module te maken. Maar alles met de PC en de ARDUINO. Die staan blijkbaar op verschillende snelheden ingesteld.

In je laatste sketch ontbreekt de Serial.begin(9600); Daarmee stel je de baudrate in op de arduino, op de verbinding naar de PC. En vervolgens moet je op de PC diezelfde baudrate instellen. 300 baud is wel erg traag, maar dat is wel een standaard waarde die door elke PC wordt ondersteund.

Om te testen kun je in de Arduino ide een terminal programma starten. Zie "Tools"-->"Serial monitor". (Wel eerst de juiste poort kiezen). Binnen de serial monitor kun je de verschillende baudrates proberen (rechts onderin).

Als alles goed staat ingesteld moet je gewoon de tekst "loop 1" "loop 2" "loop 3" etc krijgen. De 'vele spaties' zeggen niet zoveel zolang de instellingen verkeerd staan.

[Bericht gewijzigd door deKees op maandag 2 mei 2016 23:49:49 (12%)

buckfast_beekeeper

Golden Member

Of het nu de arduino, de module of een ander apparaat is, als de baudrate aan beide zijden niet gelijk is, zal het nooit goed gaan.

300Bd is voor deze toepassing voldoende. 15 byte à 8 bit is maar 120 bits. Is dus in minder dan een halve seconde verzonden. Er rest dan nog voldoende tijd om andere zaken te doen.

De 300Bd heeft ook nog het voordeel dat de verbinding minder kritisch is en over heel lange afstanden kan werken.

Van Lambiek wordt goede geuze gemaakt.

Beste

Op de Arduino site staat een voorbeeld met een software serial connectie welke een andere baudrate gebruikt dan de gewone seriële connectie. Dus ik neem aan dat dit wel kan:

https://www.arduino.cc/en/Tutorial/SoftwareSerialExample

Ik heb de inkomende data omgezet naar hex, en krijg nu het volgende:

Start sync
Stop sync
60 79 13 66 66 26 62 26 62 26 62 66 66 22 00

Baudrate naar module = 300 baud
Baudrate naar pc = 1200 baud

Kan hier nu de uren en minuten worden uit gehaald of is de data nog steeds niet juist?

code:

c code:


/*
 
 The circuit: 
 * RX is digital pin 10 (connect to TX of other device)
 * TX is digital pin 11 (connect to RX of other device)
 
 created back in the mists of time
 modified 25 May 2012
 by Tom Igoe
 based on Mikal Hart's example
 
 This example code is in the public domain.
 
 */
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup()  
{
  // Open serial communications and wait for port to open
  Serial.begin(1200);

  // Set the data rate for the module port
  mySerial.begin(300);
  
  delay(1000);
  
  // Test communication to the PC and syncronize with the signal
  Serial.print("Start sync\n");
  delay(180000);
  Serial.print("Stop sync\n");
}

void loop()
{
  // Send time protocol command
  mySerial.write(0x3F);
  delay(40);
  mySerial.write(0x0D); // <CR>
  delay(40);
  
  // Receive data
  mySerial.listen();
  if (mySerial.available()){
    // Strip down the parity bit
    char c = (mySerial.read() & 0x7F);
    
    //Serial.print(c);
    // Convert Byte to Hex
    Serial.print("0123456789ABCDEF" [(c & 0x70) >> 4]);
    Serial.print("0123456789ABCDEF" [c & 0x0F]);
    Serial.print(" ");
  }
}

Dat begint erop te lijken.
"Start sync" en "Stop sync" betekent dat de verbinding van Arduino naar PC goed staat ingesteld.

En blijkbaar reageert de klokmodule ook.
De data kun je nu opzoeken in een ascii tabel:

60 79 13 66 66 26 62 26 62 26 62 66 66 22 00
' y CR f f & b & b & b f f " NULL

Dus daar word je niet veel wijzer van.
Maar het zijn wel precies de 15 bytes die je zou verwachten.

Maar ik denk dat je nogal wat bits mist. Je gebruikt een software uart, en dat betekent waarschijnlijk dat die niet kan zenden en ontvangen tegelijk. En in je loop ga je nu telkens 2 bytes versturen en 1 byte ontvangen. Dan kan het goed zijn dat er allerlei bits wegvallen.

Dus eigenlijk moet je na het versturen van het commando blijven luisteren totdat je het hele bericht binnen hebt.

Arco

Special Member

@deKees: Zo hussel je wel de hele boel door mekaar... :)
CR = 13 is decimaal, en de rest behandel je als hex getallen?

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

@Arco, Klopt, foutje.
De Arduino converteert naar Hex, dus '13' is dan idd geen CR.

Maar verder kan ik nergens de verwachtte datum-string terughalen.
- Hardware fout aangesloten ? Niet waarschijnlijk want er komt wel iets binnen. Blijkbaar reageert de klok wel op een request.
- Dus het moet iets te maken hebben met de software uart volgens mij.

Zou de 00 dan de CR moeten voorstellen?

Ik ga eerst proberen alle bytes te ontvangen om daarna een nieuwe request te versturen zoals deKees eerst had voorgesteld.

Misschien is er inderdaad iets verkeerd aan de software UART.

Ik heb de code aangepast zodat er eerst een volledige boodschap wordt doorgestuurd alvorens een nieuwe aanvraag wordt verzonden.
Ik gebruik de 00 als CR, ik tel 18 cijfers maar weet nog steeds niet wat ze betekenen. Kan het zijn dat de software UART toch niet zo goed werkt?

c code:


void loop()
{
  // Send time protocol command
  if(data == "0" and mata == "0"){
    mySerial.write(0x3F);
    delay(40);
    mySerial.write(0x0D); //<CR>
    delay(40);
//    send = true;
  }
  
  // Receive data
  mySerial.listen();
  if (mySerial.available()){
    // Strip down the parity bit
    char c = (mySerial.read() & 0x7F);
    
    //Serial.print(c);
    // Convert Byte to Hex
    data = (String)("0123456789ABCDEF" [(c & 0x70) >> 4]);
    mata = (String)("0123456789ABCDEF" [c & 0x0F]);
    Serial.print(data);
    Serial.print(mata);
    /*Serial.print("0123456789ABCDEF" [(c & 0x70) >> 4]);
    Serial.print("0123456789ABCDEF" [c & 0x0F]);*/
    Serial.print(" ");
  }
}

Het resultaat:
Start sync
Stop sync
60 79 66 66 26 26 62 62 66 26 62 26 62 66 66 66 26 00

Ik kan proberen om een atmeega32 aan te sluiten op de module en deze met SPI ofzo te laten spreken met de Arduino en deze op zijn beurt met de pc (ik heb geen LCD scherm voor mijn atmega32).

buckfast_beekeeper

Golden Member

Van elke ontvangen byte mag je alleen de eerste nibble (bits 0-3) gebruiken. De 2de nibble (bits 4-7) bevat andere zaken. Bits 4 en 5 zijn 1, 6 is 0 en 7 is de pariteit.

0x60 = 96 = 0110 0000 zou dan geen geldige byte zijn. Omdat bit 4 0 is.
0x66 = 102 = 0110 0110 is dan ook niet geldig.
0x26 = 38 = 0010 0110 idem.

Probeer een keer alleen de eerste nibble door te zenden.

Van Lambiek wordt goede geuze gemaakt.

Wat is de eerste nibble, de data of mata variabele?

Arco

Special Member

Wat de 'eerste' nibble is, is een kwestie van interpretatie... :)
Daarom spreken we liever van LSN(ibble, bits 0...3) en MSN(ibble, bits 4...7). Data zit in LSN in dit geval.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Maar hoe kan ik nu weten wat die LSN is in mijn code?