Schwierigkeiten mit Arduino Clone

Hallo miteinander,
ich bin gerade etwas am verzweifeln weil ich ein seltsames Problem mit einem Arduino Nano Clone mit CH340 Chip habe:
Der Arduino Nano komuniziert mit einer PC-Software, die mir ein Freund programmiert hat. Das klappt recht gut. Nun tritt folgendes Problem auf: Sobald ich den PC neu starte erkennt die Software den Nano nicht mehr (im Gerätemanager ist er aufgeführt und ist korrekt installiert) Wenn ich den Sketch neu hochlade erkennt die Software den Nano wieder. Solange bis ich den PC neu starte. Seltsamerweise tritt das Problem mit einem anderen Nano nicht auf. Nur eben mit dem den ich jetzt schon so schön auf die Platine gelötet und eingebaut habe :slight_smile: Irgendwelche Ideen?

Nöö..

Keine Ideen!
Leider zeigst du weder Schaltplan, noch die beiden Software Komponenten.

Und meine Kristallkugel ist diese Woche in Urlaub!

Aber eins kann ich dir sagen:
Der Fehler steckt da, wo du ihn bis jetzt noch nicht gesucht hast.
höchstvermutlich

Hi

Heißt hier 'neu hochlade' einen komplett neuen Upload auf den Nano??
Weil: Viel mehr als ein Reset führt Der nach dem Upload auch nicht aus und Da startet das Programm, wie nach jedem Reset.

Du hast also zwei Nano, 1x eine billige, chinesische Klon-Kopie, und einen Originalen.
(nur wegen des China-Bashing)
Das China-Ding tut nicht, der Originale aber schon.

Möglich, daß der Originale anders resettet? Also der Chine-Klon später oder gar garnicht resettet, wenn die serielle Schnittstelle geöffnet wird und Dein PC-Programm eine 'Hallo ich bin's' erwartet, aber leider nur die Früchte der Arbeit vorgesetzt bekommt?

Denke, Das sollte als Ideen erst Mal reichen :wink:

MfG

Ich gehe mal davon aus das deine PC Software einen Comport auswählen muss und du dann Manuel eine Verbindung herstellst. Wenn dem nicht so ist ...... funktioniert das Polling für die Schnittstelle nicht, da es ja dann Automatisch eine Verbindung herstellen will und scheinbar keinen Arduino findet der Antwortet.
Erkläre doch erstmal wie eine Verbindung bei dir zu stande kommt.

Gruss Temucin

Hey, erst mal vielen Dank für die Antworten.

Also es ist so, dass ich die PC-Software nicht selbst geschrieben habe. Um das zu veröffentlichen müsste ich erst mal nachfragen ob das in Ordnung ist. Außerdem bin ich nicht in der Lage den richtigen Teil der PC Software zu finden, weil ich davon keine Ahnung habe... Ich weiß nur, dass die Software in C++ mit WXWidget PlugIn geschrieben ist.

Ich habe 5 baugleiche Arduino Clone (einer davon ist auf eine Platine gelötet). Bei zweien tritt das beschriebene Problem auf, bei den anderen dreien nicht. Sehr dubios. Über Geräte-Manager, Eigenschaften, Details, Hardware-ID kann ich Unterschiede feststellen. Ansonsten ist alles gleich.

Upload heiß tatsächlich ich schließe meine Software, starte die Arduino IDE, lade den Sketch via USB hoch. Schließe die Arduino SOftware und starte die eigene Software wieder. Und schon findet er den Arduino wieder.

Die PC-Software nimmt immer den ersten freien Com-Port. Da normalerweise nur der Arduino angeschlossen ist, ist die Wahrscheinlichkeit ziemlich hoch, dass der Com-Port stimmt. Ansonsten lässt sich das manuell über ein Menü korrigieren.

Die IDE verändert die Parameter der Schnittstelle, kannst Du Dir ansehen:

f:\>mode com3

Status von Gerät COM3:
----------------------
    Baudrate:        0
    Parität:         None
    Datenbits:       0
    Stoppbits:       1
    Timeout:       OFF
    XON/XOFF:        OFF
    CTS-Handshaking: OFF
    DSR-Handshaking: OFF
    DSR-Prüfung:     OFF
    DTR-Signal:      OFF
    RTS-Signal:      ON

Möglicherweise schafft es die Software nicht, die Parameter bei allen Ports richtig einzustellen. Ports mit höherer Nummer könnten Probleme machen.

Upload heiß tatsächlich ich schließe meine Software, starte die Arduino IDE, lade den Sketch via USB hoch. Schließe die Arduino SOftware und starte die eigene Software wieder. Und schon findet er den Arduino wieder.

Was den ATMega328P des Nano betrifft, ist das das gleiche, wie einfach nur Reset Knopf drücken.

Du suchst also an der falschen Ecke.

Aber da ja offensichtlich alles, außer das Problem, geheim bleiben muss, kann ich hier eigentlich nur aufgeben.
Ich bin hier auch nicht bereit, und dann auch noch gegen Widerstand, alle Würmer einzeln aus der Nase zu ziehen.

Z.B. So:
Welche USB-Serial Konverter sind auf deinen Nanos?

Oder, damit ich sagen kann:
Versehe alle mit dem gleichen Bootloader, damit sie sich gleich verhalten. Und auch die Fuses richtig gesetzt sind.

Der USB-Serial Converter ist ein CH340.

Den Bootloader habe ich zumindest auf den betroffenen Arduino mittest Programmer neu aufgespielt. Das brachte leider keine Veränderung.

Wenn der Upload einem einfachen Reset gleicht, wieso bewirkt er dann etwas anderes? Der Neustart des Arduinos brachte keine Veränderung. Der Upload mit der IDE schon.

Das mit den Schnittstellenparametern werde ich morgen gleich ausprobieren. Wenn das das Problem ist, sollte ja auch ein manuelles Anpassen der Parameter über den Gerätemanager denselben Effekt haben wie der Upload über die IDE. Dann sind die Schnittstellenparameter das Problem und ich könnte meinen Kumpel fragen ob er da in der PC-Software noch was drehen kann.

Du kannst auch testweise COM-Ports löschen und den Arduinos dann kleinere Zahlen zuweisen lassen.

Hi

Welche Schnittstellen hast Du denn zu welcher Zeit?
Denke, Dir laufen die COM-Ports nach oben weg, also zumindest höher, als das Programm Deines Kumpel sucht.

Bei mir werden die Nano als "QinHeng Electronics USB 2.0-Serial[0254]" und die Uno als ...[0262] erkannt, haben aber beide die USB-ID 1a86:7523.
Wenn ich verschiedene Nanos nacheinander einstecke (und zur VM einzeln durchreiche), bleibt das COM-Port gleich (bei mir COM7 bzw. die 2.te 'Art' bekommt dann COM8).
Bei mir sind Alle 'ch341'

MfG

Mein UNO hatte > 1 Jahr COM4. Seit 2 Wochen hat er COM14. Windows halt.

Gruß Tommy

Tommy56:
Mein UNO hatte > 1 Jahr COM4. Seit 2 Wochen hat er COM14. Windows halt.

Neuer USB-Anschluß, neue Portnummer.

Gleicher aktiver USB-HUB, dort gleicher Anschluß. Der HUB ist auch immer noch am gleichen USB-Anschluß am Rechner.

Gruß Tommy

Die Arduinos haben eine Seriennummer und darum bekommen sie immer den gleichen COM PORT und zwar den niedrigsten freien.
Man kann die vergebenen COM ports löschen und so eieder einen niedrigeren Port bekommen. Nicht alle PC-Programme können auf höhere Portnummern zugreifen.

Grüße Uwe

Hm, ich glaube nicht, nicht, dass des an der Port-Nummer liegt. Erstens war eine ziemlich niedrige Port-Nummer vergeben, zweitens werden bei der PC-Software die nicht belegten Com-Ports glrau hinterlegt und alssen sich nicht wählen. Die Software konnte konnte also erkennen, an welchem Com-Port der Arduino angeschlossen ist. Nur konnte sie eben nicht damit kommunizieren.

Hier mal der Sketch. Die Definitionen etc. (alles was ganz oben steht) musste ich weg lassen, weil der Post sonst zu lang wird. Es sind anscheinend max. 9000 Zeichen erlaubt.

/*


/// RESET-FUNKTION (Funktion als Adresse 0 festlegen & aufrufen)
void (*Neustart)(void) = 0; // Alternative ohne Hardware

/// EMPFANGSFUNKTION
void serialEvent() {
  if (Serial.available())
  {
    byte Option = (byte)Serial.read();
    /// Baudraten/Codierung (funktionierende, abhängig vom niedrigsten Interval)
    //if(Option >= (byte)100 && Option <= (byte)149) Set_Codierung(Option - (byte)100);
    //else if(Option >= (byte)50 && Option <= (byte)99) Set_Baudrate(Option - (byte)50);
    /// Andere Optionen
    if(Option==(byte)15) SHUNT_Set(true); /// SHUNT anschalten
    else if(Option==(byte)14) SHUNT_Set(false); /// SHUNT abschalten
    else if(Option==(byte)13) {Wait(); WR_Set(true);} /// WR anschalten
    else if(Option==(byte)12) {Wait(); WR_Set(false);} /// WR abschalten
    else if(Option==(byte)11) Konfiguration(); /// von PC u.a. zur Identifizierung
    else if(Option==(byte)10) {Wait(); Strom_Kalibri_All();}
    else if(Option==(byte)9) Arbeitsaufforderung(); /// vom PC zum Daten senden
    //else if(Option==(byte)8) Werkseinstellung();
    //else if(Option==(byte)7) {Serial.end(); Neustart();}
    //else if(Option==(byte)6) Zuruecksetzen();
    //else if(Option==(byte)5) Loeschen();
    //else if(Option==(byte)4) Stromkalibrierung();
    //else if(Option==(byte)3) Interval_Up();
    //else if(Option==(byte)2) Interval_Down();
    //else if(Option==(byte)1) Hintergrundbeleuchtung();
  }
/// clear the incoming/receive Serial buffer
//while(Serial.available())
  //Serial.read();
}

void setup()
{
  pinMode(WR_PORT, OUTPUT);
  digitalWrite(WR_PORT, LOW);
  WR_Set(true); /// Optional
  pinMode(SHUNT_PORT, OUTPUT);
  digitalWrite(SHUNT_PORT, LOW);
  SHUNT_Set(false); /// Optional
  ADC_Config();
  Verbinden();
  EEPROM_auslesen();
}

void loop()
{
    /// NUR FÜR DEBUG-ZWECKE
    //Debug();
}

/*
 * Der PC (Software) bittet um folgender Sachen:
*/
void Arbeitsaufforderung()
{
/// Messen und speichern
    Read_Save();
/// Datenübertragung
    Daten_senden((char*)&Data, (uint8_t)sizeof(daten)); /// über USB
}

void Konfiguration()
{
/// u.a. die Konfiguration mitteilen
      Daten_senden((char*)&Conf, (uint8_t)sizeof(configuration)); /// über USB
}

/*
 * Funktionen
 */

void EEPROM_auslesen()
{
  for(int i=0; i<(COUNT_USER+1); i++)
    EEPROM.get(EEPROM_Kalibrierung+(2*i), A_Offset[i]);
}

void Read_Save()
{
  /// Spannungs-ADC-Wert
  Data.ID_V = read_adc(0);
  /// Stromstärke-Batterie-ADC-Wert
  if(INV_BATT_W)
  {
    Data.ID_A_all = A_Offset[COUNT_USER] - (short)read_adc(1);
  }
  else
  {
    Data.ID_A_all = (short)read_adc(1) - A_Offset[COUNT_USER];
  }
  /// Stromstärke-Nutzer-ADC-Wert
  if(INV_USER_W)
  {
    for(int i=0; i<COUNT_USER; i++)
    {
      Data.ID_A[i] = A_Offset[i] - (short)read_adc(i+COUNT_USER);
    }
  }
  else
  {
    for(int i=0; i<COUNT_USER; i++)
    {
      Data.ID_A[i] = (short)read_adc(i+COUNT_USER) - A_Offset[i];
    }
  }
}

void SHUNT_Set(bool value)
{
/// SHUNT einschalten
  if(value==true)
  {
    if(digitalRead(SHUNT_PORT)==LOW)
    {
        digitalWrite(SHUNT_PORT, HIGH);
    }
  }
/// SHUNT ausschalten
  else if(value==false)
  {
    if(digitalRead(SHUNT_PORT)==HIGH)
    {
      digitalWrite(SHUNT_PORT, LOW);
    }
  }
}

void Strom_Kalibri_All()
{
/// Alle Nutzer
  for(int i=0; i<(COUNT_USER); i++)
  {
    A_Offset[i]=(short)read_adc(i+COUNT_USER);
    EEPROM.put(EEPROM_Kalibrierung+(2*i), A_Offset[i]);
  }
/// Die Allgemeine Leitung
  A_Offset[COUNT_USER]=(short)read_adc(1);
  EEPROM.put(EEPROM_Kalibrierung+(2*COUNT_USER), A_Offset[COUNT_USER]);
}

void Wait()
{
  /// Möglichkeit ALT
  //delay(WR_DELAY);
  /// Möglichkeit NEU
  unsigned long jetzt = millis();
  while((millis()-jetzt)<WR_DELAY){;}
}

void WR_Set(bool value)
{
/// WR einschalten
  if(value==true)
  {
    while(digitalRead(WR_PORT)==LOW)
    {
      if(millis()>WR_AKTIVATE)
      {
        digitalWrite(WR_PORT, HIGH);
      }
    }
  }
/// WR ausschalten
  else if(value==false)
  {
    if(digitalRead(WR_PORT)==HIGH)
    {
      digitalWrite(WR_PORT, LOW);
    }
  }
}

/*
 * Debug für Serial Monitor
 */

void Debug()
{
  for(int i=0; i<(SELPIN_Size*8); i++)
  {
    Serial.print("Channel ");
    Serial.print(i);
    Serial.print(": ");
    Serial.println(read_adc(i),DEC);
  }
  Serial.println(" ");
  for(int i=0; i<(COUNT_USER); i++)
  {
    Serial.print("Offset ");
    Serial.print(i);
    Serial.print(": ");
    Serial.println(A_Offset[i],DEC);
  }
  Serial.println(" ");
  Serial.print("Offset-All; "); Serial.println(A_Offset[COUNT_USER],DEC);
  Serial.println(" ");
  delay(INTERVAL_DEBUG); 
}

/*
 * USB Funktionen
 */

void Daten_senden(char *structPointer, byte structLength)
{
/// clear the incoming/receive Serial buffer
while(Serial.available())
  Serial.read();
  // NUR FÜR REALEN BETRIEB
  for(byte i = 0; i<structLength; i++)
    Serial.write(structPointer[i]);

/// clear the transmit/outgoing Serial buffer
Serial.flush();
}

void Verbinden()
{
  Serial.end();
  Serial.begin(BPS, CODIERUNG);
}

/*
 * ADC Funktionen
 */

void ADC_Config()
{
  /// SPI-Pin-Konfiguration am Arduino
  for(int i=0; i<SELPIN_Size; i++)
  {
    pinMode(SELPIN[i], OUTPUT);
  }
  pinMode(DATAOUT, OUTPUT); 
  pinMode(DATAIN, INPUT); 
  pinMode(SPICLOCK, OUTPUT); 
  /// Startwerte für ausgeschaltetes IC
  for(int i=0; i<SELPIN_Size; i++)
  {
    digitalWrite(SELPIN[i],HIGH);
  }
  digitalWrite(DATAOUT,LOW); 
  digitalWrite(SPICLOCK,LOW);
}

void CycleClock()
{
  digitalWrite(SPICLOCK,HIGH);
  digitalWrite(SPICLOCK,LOW); 
}

int read_adc(int channel)
{
  int CS_Pin = channel/8; // Welches IC anhand der Kanalnummer
  channel%=8; // Welcher Kanal (0-7) bei IC
  int adcvalue = 0; // analogen Wert
  byte commandbits = B11000000; // Bits: Start, Modus, Kanal (3), "Unbenutzt" (3)
  commandbits|=(channel<<3); // Kanal auswählen
  digitalWrite(SELPIN[CS_Pin],LOW); // IC-Verbindung herstellen
  for (int i=7; i>=3; i--) // Einrichtungsbits übertragen
  {
    digitalWrite(DATAOUT,commandbits&1<<i);
    CycleClock();
  }
  CycleClock(); CycleClock(); // 2 Null-Bits ignorieren
  for (int i=11; i>=0; i--) // Die Bits vom ADC-IC ermitteln
  {
    adcvalue+=(digitalRead(DATAIN)<<i);
    CycleClock();
  }
  digitalWrite(SELPIN[CS_Pin], HIGH); // IC-Verbindung trennen
  return adcvalue; // Analogen Wert zurückgeben
}

Ich halte den Kommando Parser für bedenklich, da er bei jedem Event nur 1 Symbol aus wertet. Wenn das PC Programm ähnlich ungeschickt gebaut ist, können tatsächlich die lustigsten Erscheinungen auftreten.

Auch ist der Reset Zeiger bedenklich.
Er macht eben keinen Reset.
Wozu überhaupt ein Softreset?
Aus meiner Sicht ist ein solcher Reset erheblich flüssiger als Wasser:
Er ist überflüssig!

Wenn du anstatt flashen nur den seriellen Port der IDE aufmachst, und danach die IDE beendest, was sagt dan das besagte PC-Programm?

Hi

combie:
Auch ist der Reset Zeiger bedenklich.
Er macht eben keinen Reset.
Wozu überhaupt ein Softreset?

So wie ich die Sache sehe, springt bei diesem Aufruf der µC an Adresse 0x00
Dort steht ein JMP zur Init-Routiene, Diese wird auch beim Reset aufgerufen, da dann der µC ebenfalls bei 0x00 anfängt.
(Reset-Vector)
Zumindest auf AVR basierten Arduinos sollte Das genau den gewünschten Erfolg haben, nämlich ein Reset.

Wozu?
Selber lasse ich damit Nono's nach einer Sekunde Pause resetten, wenn nicht alle notwendigen Sensoren gefunden wurden.
Ausgabe auf der seriellen Schnittstelle mit Nennung des Problem, Wartezeit, 'goto 10' (also Neustart und ein erneuter Versuch).

Wer's nicht braucht, muß Es ja nicht benutzen.
Wer's gebrauchen kann, hat so eine Möglichkeit, den µC ins Reset zu treiben.
Ja, man kann auch den WDT auf kurze Zeit stellen und ein while(1); startet - kostet aber mehr Platz und man muß beim Start des Arduino den WDT wieder deaktivieren, da Dieser - zumindest bei den ATtiny (und ich gehe davon aus, bei den 'Großen' auch) nicht selbstständig deaktiviert wird - daher eine nicht zu kurze WDT-Zeit wählen, sonst Reset-Loop.

MfG

Zumindest auf AVR basierten Arduinos sollte Das genau den gewünschten Erfolg haben, nämlich ein Reset.

Bei einem Reset werden alle Register auf Initial Zustand gesetzt, das kann der Jump nicht leisten.
Der Jump ist ein Jump, kein Reset.
Hat noch nicht mal im entferntesten eine Ähnlichkeit damit.

Selber lasse ich damit Nono’s nach einer Sekunde Pause resetten, wenn nicht alle notwendigen Sensoren gefunden wurden.

Wozu da der Reset?

Wer’s gebrauchen kann, hat so eine Möglichkeit, den µC ins Reset zu treiben.

  1. Wozu?
    Ich kann es mir nicht vorstellen.
  2. Das ist kein Reset.
  • daher eine nicht zu kurze WDT-Zeit wählen, sonst Reset-Loop.

Da steckt ein Irrtum drin.
Bei einem Reset wird der Teiler des WDT auf den kleinst möglichen Teiler initialisiert.
Egal, was du da vorher rein geschrieben hast.

Und da sind wir an dem Punkt,…
Das Reset Enable Flag ist das einzige RegisterBit, was vom Reset nicht angefasst wird.

Außerdem hat der Nano das Reset-Loop Problem, und nicht der UNO.
Denn der UNO hat einen moderneren Bootloader, welcher das verhindert.

Mein Tipp:
Also, wenn den WDT des Nano nutzen, dann vorher den Nano zum UNO umflashen.

Hi

combie:
Wozu da der Reset?

(bei nicht gefundenen Sensoren)

Den benutze ich, damit der Arduino 'vorne' erneut anfängt, eben mit dem Initiieren der Variablen, Die eben 'beim Start' so gebraucht werden.
Klar kann ich auch eine While-Schleife oder Ähnliches um den Code basteln, Den ich ganz gerne im Setup erfolgreich ausgeführt haben will - bisher geht Das aber auch durch jmp 0.
Die nicht erfolgte 'in Grundstellung bringen' sollte hier keine Nachteile bringen, da ich zuvor nicht an internen Registern geschraubt habe, Diese also noch 'in Grundstellung' sind.

Die Sache mit dem WDT habe ich vor langer Zeit gelesen und seit Dem als 'besser dran denken' im Hinterkopf - aber Du wirst wohl Recht haben und ein Blick ins entsprechende Datenblatt sollte Das dann auch zeigen, also wie der WDT initiiert wird, bei einem echtem Reset.

MfG