Arduino Mega 2560 Pin rauschen und langsame reaktion

Hallo,

ich habe mir einen Arduino Mega 2560 R3 geholt, damit ich mehr io Pins für meine CNC habe. Da das aber mein erster Arduino ist, brauche ich ein wenig hilfe. Ich habe vor, den Arduino per USB an meine CNC anzuschließen, das Programm habe ich schon fertig bekommen aber leider Rauschen die Pins sehr und wirklich reaktionsschnell ist die Übertragung auch nicht (ich weiß nicht, ob es am Arduino, an der Übertragung zur CNC oder an Linuxcnc liegt aber schneller als ein paar Sekunden sollte doch möglich sein, oder?). Im Prinzip möchte ich Pins 22 bis 53 für io haben (3-6 Pins sollen Output werden, der Rest Input) wenn es geht. Hauptsache ist, dass die Signale stabil sind!

Ich habe das Programm angefügt, falls mir jemand helfen kann, wäre ich sehr dankbar dafür!

//arduinosend.ino
#include <SoftwareSerial.h>
#include "Wire.h"

void setup() 
{
    Serial.begin(9600);
    for(int x = 14; x < 50; x++)pinMode(x, INPUT);
}

void loop() 
{
int x, y, z;  
uint8_t  buff[5];

    buff[4] = '\0';
    z = 14;
    for(x = 0; x < 4; x++) // 4 packets 8 bits
        for(y = 0; y < 8 ; y++) bitWrite(buff[x], y, digitalRead(z++));
    Serial.write(buff, 4);
    delay(1000);    
}

Mfg

arduinosend.ino (410 Bytes)

Wenn Du willst, das Dein Programm jemand liest, dann stelle es in Codetags (oben links im Foreneditor </>). Anhänge liest kaum einer. Das kannst Du auch durch editieren erreichen.

Ein Schaltplan wäre zum Verständnis auch nicht schädlich.

Gruß Tommy

Hallo, die Signale Deiner Pin´s 22 bis 53 vagabundieren sicher nicht- durch die Gegend, weil Du sie ja gegen Masse gezogen hast!? Gruß und Spaß Andreas

P.S. Die "SoftwareSerial.h" brauchst Du im Sketch auch nicht. Damit "Serial.begin(9600)" sprichst Du auch den "USB" des Mega an. Was sollte denn da der Empfänger sein? Das "delay(1000)" haut Dir jedesmal 1 Sekunde "nichts tun" rein…

WAS machst Du da? Was hast Du vor? Dein NickName hast Du ja passend gewählt...

Du brauchst den Buffer nicht, ebenso nicht die schließende 0.
Du benutzt an vielen Stellen ints, wo byte ausreichten.
Du setzt den pinMode auf den Standardwert, überflüssig.
Du includest unbenutzte Libraries, warum?

Ich sehe neben den schon genannten Punkten noch ein viel gravierenderes Problem.

Es wird binär übertragen, ohne jedes Framing/Header/Trailer… wie willst du da den Anfang erkennen?

An der Pause, die du nicht machen willst, weil es ja zu langsam geht?

Ich würde die Werte in Hex übertragen und die Zeilen mit CR/LF abschließen.

10 Bytes pro Abtastung, dafür aber lesbar und einfach zu verarbeiten.

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

void loop() {
  uint8_t z = 14;
  for (uint8_t x = 0; x < 4; x++) { // 4 x 8 bits
    uint8_t eightBits;
    for (uint8_t y = 0; y < 8; y++) {
      bitWrite(eightBits, y, digitalRead(z++));
    }
    if (eightBits < 16) {
      Serial.write('0');
    }
    Serial.print(eightBits, HEX);
  }
  Serial.println();
}

Mit einer Variante die misst, wie oft sie in der Sekunde ausgibt,

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

void loop() {
  static unsigned long iterations;
  static unsigned long lastSecond;
  unsigned long topLoop = millis();
  iterations++;
  uint8_t z = 14;
  for (uint8_t x = 0; x < 4; x++) { // 4 x 8 bits
    uint8_t eightBits;
    for (uint8_t y = 0; y < 8; y++) {
      bitWrite(eightBits, y, digitalRead(z++));
    }
    if (eightBits < 16) {
      Serial.write('0');
    }
    Serial.print(eightBits, HEX);
  }
  Serial.println();
  if (topLoop - lastSecond >= 1000) {
    Serial.print(iterations);
    Serial.println(F(" / second"));
    iterations = 0;
    lastSecond = topLoop;
  }
}

erhält man (gefiltert)

2087 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2084 / second
2082 / second
2084 / second
2081 / second
2085 / second
2081 / second
2085 / second
2081 / second
2084 / second
2085 / second
2081 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2084 / second
2082 / second
2084 / second
2082 / second
2084 / second
2082 / second

Hallo,

Danke erstmal für die Antworten, meinen Nicknamen habe ich fast überall, ist ne lange Geschichte :wink:

die Schaltung ist so ziemlich trivial, einfach 3,3 oder 5V in einen Taster rein und vom Taster in einen beliebigen Pin (Pins muss ich mir noch aussuchen, habe nur testweise einen Taster in verschiedene Pins gesteckt und schon beim reinstecken hat der Arduino manchmal mehrere Signale gesendet). Der Empfänger ist wie gesagt Linuxcnc (für das ich auch ein extra Programm kompilieren musste).

Im Prinzip möchte ich mit mehreren Tastern verschiedene Funktionen ausführen wie zB. Programm start/Stop/Fortfahren oder aber auch Kühlmittel An/Aus und dementsprechend auch die LED´s der Taster Blinken oder Leuchten lassen.

falls es was bringt, hier ist der Code vom Programm für Linuxcnc:

//serialreceive.comp
component serialreceive              "Receiving 32 bits data from arduino";

pin out bit bit-##[32] = false       "Output bits";

option singleton yes;               
option userspace yes;

author "ArcEye arceye@mgware.co.uk";
license "GPL";
;;

#include <stdio.h>    /* Standard input/output definitions */
#include <stdlib.h> 
#include <stdint.h>   /* Standard types */
#include <string.h>   /* String function definitions */
#include <unistd.h>   /* UNIX standard function definitions */
#include <fcntl.h>    /* File control definitions */
#include <errno.h>    /* Error number definitions */
#include <termios.h>  /* POSIX terminal control definitions */
#include <sys/ioctl.h>

#define BAUDRATE B9600
#define DEVICE "/dev/ttyACM0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

int serialport_init();
                             
struct termios toptions;;       // port setup

void user_mainloop(void)
{
int c, x, y, z;
char ch;
int fd = serialport_init();
  
    while (fd != -1) 
        {
        usleep(1000000);
        FOR_ALL_INSTS() 
            {
            z = 0;
            for(x = 0; x < 4; x++) // 4 packets 8 bits
                {
                read(fd,&ch,1); 
                for(y = 0; y < 8 ; y++) bit(z++) = bitRead(ch, y);
                }
            // test - to show that bits were written
            // comment out next 3 lines when using for real
            //for(x = 0; x < 32; x++) 
            //    fprintf(stderr,"%d",bit(x));
            //fprintf(stderr,"\n");
            }
        }
    close(fd);
    exit(0);
}


//######################################################################

int serialport_init()
{
int fd;
 
    fd = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)  
        {
        perror("init_serialport: Unable to open port ");
        return -1;
        }
    if (tcgetattr(fd, &toptions) < 0) 
        {
        perror("init_serialport: Couldn't get term attributes");
        return -1;
        }
    speed_t brate = BAUDRATE; 
    cfsetispeed(&toptions, brate);
    cfsetospeed(&toptions, brate);
    // 8N1
    toptions.c_cflag &= ~PARENB;
    toptions.c_cflag &= ~CSTOPB;
    toptions.c_cflag &= ~CSIZE;
    toptions.c_cflag |= CS8;
    // no flow control
    toptions.c_cflag &= ~CRTSCTS;
    toptions.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
    toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
    toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
    toptions.c_oflag &= ~OPOST; // make raw
    toptions.c_cc[VMIN]  = 0;
    toptions.c_cc[VTIME] = 20;
    if( tcsetattr(fd, TCSANOW, &toptions) < 0) 
        {
        perror("init_serialport: Couldn't set term attributes");
        return -1;
        }
    return fd;
}

die beiden Programme sind schon ca. 5 Jahre alt und aus einem Forum, könnte also schon etwas verbessert werden.

Danke Whandall, das werde ich mir mal anschauen :slight_smile: Die Baudrate von 250.000 muss ich so lassen oder kann ich die auch auf 9600 ändern? wie gesagt, das Programm habe ich schon fertig bekommen

Was meinst Du mit rauschen? Daß Du mal HIGH und mal LOW als Auslesewert bekommst? Ich vermute mal Du hast nichts an die Pins angeschlossen.

Versuch mal mit "pinMode(x, INPUT_PULLUP);" statt "pinMode(x, INPUT);" Wenn Du Taster verwendest dann brauchst Du Pullup- bzw Pulldownwiderstände. Einen Taster am pin anschließen reicht nicht.

Die Ausgabe ist langsam weil Du mit "delay(1000);" die Ausgabe nur 1x pro Sekunde machst.

Grüße Uwe

Ich würde auf beiden Seiten die höchste funktionierende Baudrate benutzen.

Die Empfangsroutine ist grottenschlecht und delay gesteuert, wegschmeißen und neuschreiben.

Für INPUT_PULLUP geht "einfach 3,3 oder 5V in einen Taster rein und vom Taster in einen beliebigen Pin" nicht mehr, du musst dann GND via Taste auf den Pin legen.

Hier kannst du sehen, wie du den Effekt (LOW gedrückt, HIGH nicht gedrückt) bei der Übertragung
wieder korrigieren kannst, also erfährt der Host nicht, dass sich die Logik geändert hat.

void setup() {
  for (uint8_t pin = 14; pin < 14 + 32; pin++) {
    pinMode(pin, INPUT_PULLUP);
  }
  Serial.begin(250000);
}

void loop() {
  static unsigned long iterations;
  static unsigned long lastSecond;
  unsigned long topLoop = millis();
  iterations++;
  uint8_t pin = 14;
  for (uint8_t bytes = 0; bytes < 4; bytes++) {
    uint8_t eightBits = 0;
    for (uint8_t bits = 0; bits < 8; bits++) {
      bitWrite(eightBits, bits, !digitalRead(pin++)); // HIGH als 0, LOW als 1
    }
    if (eightBits < 16) {
      Serial.write('0');
    }
    Serial.print(eightBits, HEX);
  }
  Serial.println();
  if (topLoop - lastSecond >= 1000) {
    Serial.print(iterations);
    Serial.println(F(" / second"));
    iterations = 0;
    lastSecond = topLoop;
  }
}

Das "hat beim reinstecken mehrere Signale gesendet" ist ganz normal.

Such mal nach dem Begriff Tasterprellen, das sollte weiter helfen.

Grüsse Peter

Hallo,

danke erst mal für die vielen Antworten, ist der letzte Code von Whandall funktionstüchtig zum Testen? Arduino nutzt eine neue Sprache, welche ich erst mal lernen muss, von daher sagt mir der meiste Teil des Codes relativ wenig.

Das ist keine neue Sprache, sondern eine sehr alte: C/C++

Gruß Tommy

sorry, nicht korrekt ausgedrückt, ich meinte für mich ist es eine neue Sprache :slight_smile:

ManMadeDesaster: ist der letzte Code von Whandall funktionstüchtig zum Testen?

Ja. der spuckt die Daten in HEX aus mit CR/LF getrennt. Jede Sekunde gibt er zusätzlich aus, wieviele Messungen die letzte Sekunde hatte, also alle 2000+ Zeilen.

okay vielen dank Whandall :) Daumen nach Oben