Ich hab das 1,5x erwähnt und auch gesagt, dass das meine Ansicht ist, ich dich aber tun lasse
Ich unterstütze trotzdem wo ich kann denn ich finde das Projekt cool.
Und aus meinem soll auch noch ein Bot werden, da möchte ich doch auch Hilfe haben, und ich hab auch viel vor *schiefgrins*
Entwicklung: RoPi - Autonomer Roboter mit RaspberryPI
-
meigrafd -
7. Juli 2014 um 20:10 -
Erledigt
Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
-
-
Entwicklung: RoPi - Autonomer Roboter mit RaspberryPI? Schau mal ob du hier fündig wirst!
-
Ich hab jetzt erst mal ein einfaches Python Script geschrieben was 2 Threads erzeugt:
- der erste stellt eine Verbindung zum Serial Port her und gibt alles in der Konsole aus
- der zweite stellt einen socket_server zur VerfügungNun hab ich aber leider das Problem dass sich der socket_server Thread beendet sobald ein Client die Verbindung trennt - Wie kann ich das beheben
Server.py:
Spoiler anzeigen
Python
Alles anzeigen#!/usr/bin/python # -*- config: utf-8 -*- import threading import serial import time import sys import socket #import signal # thread docu: http://www.tutorialspoint.com/python/python_multithreading.htm # serial docu: http://pyserial.sourceforge.net/pyserial.html # signal docu: http://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python #initialization and open the port. #possible timeout values: # 1. None: wait forever, block call # 2. 0: non-blocking mode, return immediately # 3. x, x is bigger than 0, float allowed, timeout block call ser = serial.Serial() ser.port = "/dev/ttyACM0" ser.baudrate = 9600 ser.bytesize = serial.EIGHTBITS #number of bits per bytes ser.parity = serial.PARITY_NONE #set parity check: no parity ser.stopbits = serial.STOPBITS_ONE #number of stop bits #ser.timeout = None #block read ser.timeout = 1 #non-block read #ser.timeout = 2 #timeout block read ser.xonxoff = False #disable software flow control ser.rtscts = False #disable hardware (RTS/CTS) flow control ser.dsrdtr = False #disable hardware (DSR/DTR) flow control ser.writeTimeout = 2 #timeout for write socketport = 7070 def read_Thread(): global ser print "Starte Unterprogramm: serial read" while True: try: response = ser.readline() print(response), sys.stdout.flush() except KeyboardInterrupt: print "Schliesse Unterprogramm: serial read" ser.close() thread1.exit() sys.exit() ser.close() def socket_Thread(): global ser, socketport print "Starte Unterprogramm: socket server" sock = socket.socket() sock.bind(('', socketport)) sock.listen(1) conn, addr = sock.accept() while True: try: data = conn.recv(1024) if data: print("socket Received: {}".format(data)), ser.write(data) except KeyboardInterrupt: print "Schliesse Unterprogramm: socket server" conn.close() thread2.exit() #conn.close() try: ser.open() except Exception, e: print "Error open serial port: " + str(e) exit() if ser.isOpen(): try: ser.flushInput() #flush input buffer, discarding all its contents ser.flushOutput() #flush output buffer, aborting current output and discard all that is in buffer thread1=threading.Thread(target=read_Thread) thread2=threading.Thread(target=socket_Thread) thread1.start() thread2.start() print "read_Thread ist aktiv: ", thread1.isAlive() print "socket_Thread ist aktiv: ", thread2.isAlive() print "Insgesamt sind ", threading.active_count(), " Threads aktiv." except Exception, e1: print "Error communicating...: " + str(e1) else: print "Cannot open serial port " # this is the main (3.) thread which exists after all is done, so Dont close ser here!
Client.py:
Spoiler anzeigen
PS: Der read_Thread lässt sich leider auch nicht via STRG+C beenden.
-
Hi,
Python ... weiss ich jetzt nicht.
In C ist das jedenfalls so, dass der Server für jede Verbindung einen eigenen Prozess/Thread mit einem neuen socket erzeugt, während der ursprügliche wieder in den "Listen" Modus geht.cheers,
-ds- -
Habs hingekriegt, aber eben etwas anders:
"SerialServer.py"
Python
Alles anzeigen#!/usr/bin/python # -*- config: utf-8 -*- # # Starts one Thread for Serial Reading/Writing RaspberryPI<->Arduino # Starts another Thread for Socket Server to send Commands to Arudino # # version: 0.3 # import settings import threading import serial import time import sys import socket #import signal try: import SocketServer as socketserver except ImportError: import socketserver # thread docu: http://www.tutorialspoint.com/python/python_multithreading.htm # serial docu: http://pyserial.sourceforge.net/pyserial.html # signal docu: http://stackoverflow.com/questions/1112343/how-do-i-capture-sigint-in-python # socketserver docu: https://docs.python.org/2/library/socketserver.html #initialization and open the port. #possible timeout values: # 1. None: wait forever, block call # 2. 0: non-blocking mode, return immediately # 3. x, x is bigger than 0, float allowed, timeout block call ser = serial.Serial() ser.port = settings.SerialPort ser.baudrate = settings.SerialBaudrate ser.bytesize = serial.EIGHTBITS #number of bits per bytes ser.parity = serial.PARITY_NONE #set parity check: no parity ser.stopbits = serial.STOPBITS_ONE #number of stop bits #ser.timeout = None #block read ser.timeout = 1 #non-block read #ser.timeout = 2 #timeout block read ser.xonxoff = False #disable software flow control ser.rtscts = False #disable hardware (RTS/CTS) flow control ser.dsrdtr = False #disable hardware (DSR/DTR) flow control ser.writeTimeout = 2 #timeout for write #------------------------------------------------------------------- try: DEBUG except NameError: DEBUG = False else: if DEBUG: print "Enabling DEBUG mode!" #http://www.gossamer-threads.com/lists/python/python/375364 def awk_it(instring,index,delimiter=" "): try: return [instring,instring.split(delimiter)[index-1]][max(0,min(1,index))] except: return "" def ParseSerialInput(line): prefix = awk_it(line, 1) if (prefix == "distance:"): distance = awk_it(line, 2) print "Distance: "+ distance, if (prefix == "Bearing:"): Bearing = awk_it(line, 2) Pitch = awk_it(line, 4) Roll = awk_it(line, 6) print "Bearing: "+ Bearing, print "Pitch: "+ Pitch, print "Roll: "+ Roll, sys.stdout.flush() def send_data(line): output = "%s\r\n" % (line) try: bytes = ser.write(output) except Exception, e3: print "Error sending via serial port: " + str(e3) # Flush input buffer, if there is still some unprocessed data left ser.flush() # Try to send old message ser.flushInput() # Delete what is still inside the buffer def Serial_read_Thread(): print "Starte Thread: serial read" while True: try: # Remove newline character '\n' #response = ser.readline().strip() response = ser.readline() if DEBUG: print(response), sys.stdout.flush() ParseSerialInput(response) except KeyboardInterrupt: print "Schliesse Unterprogramm: serial read" ser.close() read_thread.exit() sys.exit() except serial.SerialException as e4: print "Could not open serial port '{}': {}".format(settings.SerialPort, e4) ser.close() class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler): def handle(self): #print "aktueller thread: "+threading.current_thread() # self.rfile is a file-like object created by the handler; # we can now use e.g. readline() instead of raw recv() calls self.data = self.rfile.readline().strip() print "{} wrote: ".format(self.client_address[0]), print self.data # Likewise, self.wfile is a file-like object used to write back to the client self.wfile.write(self.data.upper()) try: send_data(self.data) except Exception, e2: print "Error sending via serial port: " + str(e2) class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer): pass if __name__ == '__main__': try: ser.open() except Exception, e: print "Error open serial port: " + str(e) exit() if ser.isOpen(): try: ser.flushInput() #flush input buffer, discarding all its contents ser.flushOutput() #flush output buffer, aborting current output and discard all that is in buffer HOST, PORT = settings.SocketHost, settings.SocketPort socket_server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) ip, port = socket_server.server_address # Start a thread with the server - that thread will then start one more thread for each request socket_server_thread = threading.Thread(target=socket_server.serve_forever) socket_server_thread.start() # Start Serial read Thread read_thread = threading.Thread(target=Serial_read_Thread) read_thread.start() print "read_Thread ist aktiv: ", read_thread.isAlive() print "socket_server_thread ist aktiv: ", socket_server_thread.isAlive() #print "Socket Server loop running in thread:", socket_server_thread.name thread_count = threading.active_count() print "Insgesamt sind ", thread_count, " Threads aktiv." except Exception, e1: print "Error communicating...: " + str(e1) else: print "Cannot open serial port " # this is the main (3.) thread which exits after all is done, so Dont close ser here!
"settings.py"
"client.py"
Python
Alles anzeigen#!/usr/bin/python # -*- config: utf-8 -*- import socket import sys HOST, PORT = "localhost", 7070 data = " ".join(sys.argv[1:]) # Create a socket (SOCK_STREAM means a TCP socket) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: # Connect to server and send data sock.connect((HOST, PORT)) sock.sendall(data + "\n") # Receive data from the server and shut down received = sock.recv(1024) finally: sock.close() print "Sent: {}".format(data) print "Received: {}".format(received)
Aufruf: client.py search:1
Derzeitige Ausgabe:
"SerialServer Ausgabe"
Code
Alles anzeigenroot@raspberrypi:~/RoPi# python SerialServer.py read_Thread ist aktiv: True socket_server_thread ist aktiv: True Insgesamt sind 3 Threads aktiv. Starte Thread: serial read Bearing: 52.30 Pitch: 0 Roll: 0 Bearing: 52.30 Pitch: 0 Roll: 0 Bearing: 52.70 Pitch: 0 Roll: 0 Bearing: 52.50 Pitch: 0 Roll: 0 Bearing: 53.00 Pitch: 0 Roll: 0 Bearing: 52.60 Pitch: 0 Roll: 0 Bearing: 52.50 Pitch: 0 Roll: 0 Bearing: 52.10 Pitch: 0 Roll: 0 127.0.0.1 wrote: hallo du da Bearing: 52.00 Pitch: 0 Roll: 0 Bearing: 51.30 Pitch: 0 Roll: 0 Bearing: 51.20 Pitch: 0 Roll: 0 Bearing: 51.40 Pitch: 0 Roll: 0 127.0.0.1 wrote: *wink* Bearing: 52.00 Pitch: 0 Roll: 0 Bearing: 52.30 Pitch: 0 Roll: 0 [...]
Nun hauch ich dem erstmal ein bisschen Intelligenz ein
-
Hab jetzt erst noch mal am motor_driver.ino weiter gemacht und Commands eingebaut um PanTilt Ein- und Aus-zuschalten. Beim Command stop:1 (egal was für ne Zahl) werden zudem die Servo's detached da diese sonst permanent an sind also Geräusche von sich geben..
Es wird auch der aktuelle Modus gespeichert, der im loop() abgefragt wird und somit fortlaufend ist - also zB search:1 läuft solange weiter bis ich ein stop:1 übermittel. Dh ich hab dort nirgends delay()'s oä. drin (abgesehen für die PanTilt function) oder while Schleifen drin, die den Sketch aufhalten oder ausbremsen würden.
Hab den Code auch noch etwas optimiert und aufgeräumt - ist aber noch immer nicht fertig
"motor_driver.ino"
C
Alles anzeigen/* Um Befehle vom RaspberryPI zu empfangen und fuer den MotorDriver umzusetzen version 0.7 by meigrafd */ /* GRID MAP Docus: http://www.robotc.net/blog/2011/08/08/robotc-advanced-training/ */ //------------------------------------------------------------------------------ #include <stdint.h> #include <Servo.h> // https://code.google.com/p/arduino/source/browse/trunk/libraries/Servo/Servo.h #include <Wire.h> // needed for CMPS10 Compass #include <CMPS10.h> //#include "RoPi_config.h" //#include <arduino.h> //------------------------------------------------------------------------------ //#define DEBUG 1 #define SERIAL_BAUD 38400 //115200 // HC-SR04 //5V on Arduino to VCC of HC-SR04 //Pin 10 of Arduino to TRIG of HC-SR04 //Pin 11 of Arduino to ECHO of HC-SR04 //GND of Arduino to GND of HC-SR04 #define ULTRASONIC_TRIG 11 #define ULTRASONIC_ECHO 10 #define MAX_DISTANCE 500 /**< maximum distance to track with sensor (in centimeters). Maximum sensor distance is rated at 400-500cm. */ #define MIN_DISTANCE 0 /**< minimum distance to track with sensor */ #define PING_INTERVAL 330 // 33 Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo). #define pingLED 13 // Arduino UNO Onboard LED //ScannerServo Pan/Tilt pins #define ScannerServoPan 8 #define ScannerServoTilt 9 // TB6612FNG Motor Driver /*Pins for the left track*/ #define PWMA 3 #define AIN1 0 #define AIN2 1 /*Pins for the right track*/ #define PWMB 5 #define BIN1 2 #define BIN2 4 // Motor Driver Standby Pin #define STBY 6 // Motor Driver LED #define motorLED 7 // Error LED #define ErrorLED 12 //CMPS10 Compass #define COMPASS_I2C_ADDRESS 0x60 // needed: á 1k8 or 4k7 resistors between: // Arduino pin A4 and 5V -> CMPS10 SCL // Arduino pin A5 and 5V -> CMPS10 SDA // Only A4 and A5 can be used for I2C! http://playground.arduino.cc/Learning/Pins //Odo Encoder #define OdoTrig A1 #define leftEncoder A2 #define rightEncoder A3 //------------------------------------------------------------------------------ // Radsensoren (Rotary Encoder) int leftValue = 0; int rightValue = 0; int left_last = 0; // alter Wert int left_actual = 0; //jetztiger Wert int right_last = 0; // alter Wert int right_actual = 0; //jetztiger Wert int totpunkt_low = 150; int totpunkt_high = 250; int LeftCounter = 0; int RightCounter = 0; //------------------------------------------------------------------------------ // Ultrasonic Sensor unsigned long pingTimer; long duration, distance, distanceCM; // Duration used to calculate distance // Scannerservo lenkt den Ultrasonic const int ScannerServoMaxPan = 160; // Max Pan servo angle in degrees. Don't go to very end of servo travel which may not be all the way from 0 to 180. const int ScannerServoMinPan = 10; // Min Pan servo angle in degrees. const int ScannerServoMaxTiltUP = 110; // Max Tilt UP position const int ScannerServoMaxTiltDOWN = 180; // Max Tilt DOWN position const int ScannerServoPanSteps = 10; const int ScannerServoTiltSteps = 30; const int ScannerServoWait = 330; // Milliseconds between Step Changes int pos_pan = 65; // variable to store the servo position int pos_tilt = 150; // variable to store the servo position int start_pos_pan = pos_pan; // this is the start pos int start_pos_tilt = pos_tilt; // this is the start pos //dont change! #define UP (1) #define DOWN (2) #define RIGHT (3) #define LEFT (4) // int dir_pan = RIGHT; // pan default direction int dir_tilt = UP; // tilt default direction int newLine = 0; int PanTilt_initializated = 0; // Zeitmessung long lastcmdtime = micros(); //Zeit des letzten Kommandos String lastcmd; //letztes ausgeführte Kommando long lastsend = micros(); //Zeit des letzten Kommandos long actual = micros(); // aktuelle Zeit int ValidCommand = 0; String ActiveMode; // speichern des aktuellen Modus: STOP / Search / AutoDrive / ManualDrive // Buffer to store incoming commands from serial port String dataString; //------------------------------------------------------------------------------ Servo pan_ScannerServo; Servo tilt_ScannerServo; CMPS10 compass; //######################################################################## // blink led for n times void blinkLED (byte pin, byte n = 3) { pinMode(pin, OUTPUT); for (byte i = 0; i < 2 * n; ++i) { delay(100); digitalWrite(pin, !digitalRead(pin)); } } static void motorDriverState (byte state) { digitalWrite(STBY, state); } // Auswertung der Radencoder um zu wissen wieviel Strecke zurueck gelegt wurde (muss bei jeder Bewegung ausgefuehrt werden) // Die Odometrie muß so oft es geht abgefragt werden, da keine Interrupts möglich sind void counter() { digitalWrite(OdoTrig, HIGH); leftValue = analogRead(leftEncoder); // read the input pin (0 to 1023) rightValue = analogRead(rightEncoder); // read the input pin (0 to 1023) digitalWrite(OdoTrig, LOW); if (leftValue < totpunkt_low) left_actual = 0; if (leftValue > totpunkt_high) left_actual = 1; if (left_last != left_actual) { LeftCounter++; left_last = left_actual; } if (rightValue < totpunkt_low) right_actual = 0; if (rightValue > totpunkt_high) right_actual = 1; if (right_last != right_actual) { RightCounter++; right_last = right_actual; } Serial.print("LeftEncoder: "); Serial.println(LeftCounter); Serial.print("RightEncoder: "); Serial.println(RightCounter); //Radsensoren zuruecksetzen, nachdem die Werte uebertragen wurden. LeftCounter = 0; RightCounter = 0; } // used with CMPS10 lib void Compass() { Serial.print("Bearing: "); // Peilung Serial.print(compass.bearing()); Serial.print(" Pitch: "); // Gefaelle Serial.print(compass.pitch()); Serial.print(" Roll: "); // Neigung Serial.println(compass.roll()); } /* used without CMPS10 lib void Compass() { byte highByte, lowByte, fine; // highByte and lowByte store high and low bytes of the bearing and fine stores decimal place of bearing char pitch, roll; // Stores pitch and roll values of CMPS10, chars are used because they support signed value int bearing; // Stores full bearing Wire.beginTransmission(COMPASS_I2C_ADDRESS); //starts communication with CMPS10 Wire.write(2); //Sends the register we wish to start reading from Wire.endTransmission(); Wire.requestFrom(COMPASS_I2C_ADDRESS, 4); // Request 4 bytes from CMPS10 while(Wire.available() < 4); // Wait for bytes to become available highByte = Wire.read(); lowByte = Wire.read(); pitch = Wire.read(); roll = Wire.read(); bearing = ((highByte<<8)+lowByte)/10; // Calculate full bearing fine = ((highByte<<8)+lowByte)%10; // Calculate decimal place of bearing Serial.print("Bearing: "); // Peilung Serial.print(bearing); Serial.print(" Bearing decimal: "); // Peilung Serial.print(fine); Serial.print(" Pitch: "); // Gefaelle Serial.print(pitch); Serial.print(" Roll: "); // Neigung Serial.println(roll); } int Compass_soft_ver() { int data; // Software version of CMPS10 is read into data and then returned Wire.beginTransmission(COMPASS_I2C_ADDRESS); // Values of 0 being sent with write need to be masked as a byte so they are not misinterpreted as NULL this is a bug in arduino 1.0 Wire.write((byte)0); // Sends the register we wish to start reading from Wire.endTransmission(); Wire.requestFrom(COMPASS_I2C_ADDRESS, 1); // Request byte from CMPS10 while(Wire.available() < 1); data = Wire.read(); return(data); } */ // Ultrasonic Ping long ping() { // The PING))) is triggered by a HIGH pulse of 2 or more microseconds. // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: digitalWrite(ULTRASONIC_TRIG,LOW); delayMicroseconds(2); digitalWrite(ULTRASONIC_TRIG,HIGH); delayMicroseconds(10); digitalWrite(ULTRASONIC_TRIG,LOW); // The ECHO pin is used to read the signal from the PING))): a HIGH // pulse whose duration is the time (in microseconds) from the sending // of the ping to the reception of its echo off of an object. duration = pulseIn(ULTRASONIC_ECHO, HIGH); // convert the time into a distance //distance = microsecondsToInches(duration); distance = microsecondsToCentimeters(duration); if (distance >= MAX_DISTANCE || distance <= MIN_DISTANCE){ // Turn LED ON to indicate "out of range" distance = -1; digitalWrite(pingLED, HIGH); } else { // Turn LED OFF to indicate successful reading. digitalWrite(pingLED, LOW); } Serial.print("distance: "); Serial.println(distance); } long microsecondsToInches(long microseconds) { // According to Parallax's datasheet for the PING))), there are // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per // second). This gives the distance travelled by the ping, outbound // and return, so we divide by 2 to get the distance of the obstacle. return microseconds / 74 / 2; } long microsecondsToCentimeters(long microseconds) { // The speed of sound is 340 m/s or 29 microseconds per centimeter. // The ping travels out and back, so to find the distance of the // object we take half of the distance travelled. return microseconds / 29 / 2; } //schrittweise void servo_pan(int pos) { static int old_pos=0; int difference = pos - old_pos; for (int i=0; i < (abs(difference) + 1); i++) { if (difference > 0) pan_ScannerServo.write(old_pos++); else if (difference<0) pan_ScannerServo.write(old_pos--); else { pan_ScannerServo.write(pos); break; } delay(15); //give the servos some time to get in position } old_pos=pos; } //schrittweise void servo_tilt(int pos) { static int old_pos=0; int difference = pos - old_pos; for(int i=0; i < (abs(difference) + 1); i++) { if (difference > 0) tilt_ScannerServo.write(old_pos++); else if (difference < 0) tilt_ScannerServo.write(old_pos--); else { tilt_ScannerServo.write(pos); break; } delay(15); //give the servos some time to get in position } old_pos=pos; } void PanTilt(void) { if (PanTilt_initializated == 0) { InitPanTilt(); } servo_tilt(pos_tilt); servo_pan(pos_pan); delay(ScannerServoWait); #ifdef DEBUG Serial.print("Pan: "); Serial.print(pos_pan, DEC); Serial.print(", Tilt: "); Serial.print(pos_tilt, DEC); #endif if (dir_pan == RIGHT) { pos_pan = pos_pan + ScannerServoPanSteps; if (pos_pan > ScannerServoMaxPan) { pos_pan = pos_pan - ScannerServoPanSteps; dir_pan = LEFT; newLine = 1; } } else { pos_pan = pos_pan - ScannerServoPanSteps; if (pos_pan < ScannerServoMinPan) { pos_pan = pos_pan + ScannerServoPanSteps; dir_pan = RIGHT; newLine = 1; } } if (newLine) { #ifdef DEBUG Serial.print(", newLine: "); Serial.print(newLine, DEC); #endif newLine = 0; if (dir_tilt == UP) { pos_tilt = pos_tilt - ScannerServoTiltSteps; if (pos_tilt < ScannerServoMaxTiltUP) { pos_tilt = pos_tilt + (ScannerServoTiltSteps * 2); dir_tilt = DOWN; } } else { pos_tilt = pos_tilt + ScannerServoTiltSteps; if (pos_tilt > ScannerServoMaxTiltDOWN) { pos_tilt = pos_tilt - (ScannerServoTiltSteps * 2); dir_tilt = UP; } } } #ifdef DEBUG Serial.println(""); #endif ping(); } void InitPanTilt() { pan_ScannerServo.attach(ScannerServoPan); tilt_ScannerServo.attach(ScannerServoTilt); tilt_ScannerServo.write(pos_tilt); pan_ScannerServo.write(pos_pan); PanTilt_initializated = 1; delay(15); //give the servos some time to get in position } void ReleasePanTilt() { tilt_ScannerServo.write(start_pos_tilt); pan_ScannerServo.write(start_pos_pan); delay(200); //give the servos some time to get in position pan_ScannerServo.detach(); tilt_ScannerServo.detach(); PanTilt_initializated = 0; } // manual move pan servo and detach after reaching position //note: the read() function of Servo.h does not give the realy actual position, its only the last write() value! // to fix this issue: http://www.mafu-foto.de/elektronik/servos/104-servos-um-positionsrueckmeldung-erweitern void move_servo_pan(int pos) { Serial.print("pos: "); Serial.println(pos); pan_ScannerServo.attach(ScannerServoPan); pan_ScannerServo.write(pos); volatile int cn = 0; do { cn++; Serial.print("cn: "); Serial.println(cn); delay(20); } while (cn < pos); delay(200); pan_ScannerServo.detach(); } // manual move tilt servo and detach after reaching position void move_servo_tilt(int pos) { tilt_ScannerServo.attach(ScannerServoTilt); tilt_ScannerServo.write(pos); volatile int cn = 0; do { cn++; delay(20); } while (cn < pos); delay(200); tilt_ScannerServo.detach(); } void goFWD(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); counter(); } void goREV(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); counter(); } void rotateLeft(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); counter(); } void rotateRight(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); counter(); } //only one side, left track void rotateLeft1f(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, HIGH); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); counter(); } //only one side, left track void rotateRight1f(int pwmWert) { digitalWrite(AIN1, HIGH); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); counter(); } //only one side, right track void rotateLeft1r(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, HIGH); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); counter(); } //only one side, right track void rotateRight1r(int pwmWert) { digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, HIGH); digitalWrite(BIN2, LOW); analogWrite(PWMA, pwmWert); analogWrite(PWMB, pwmWert); counter(); } void Stop() { ActiveMode = "STOP"; ReleasePanTilt(); digitalWrite(AIN1, LOW); digitalWrite(AIN2, LOW); digitalWrite(BIN1, LOW); digitalWrite(BIN2, LOW); analogWrite(PWMA, 0); analogWrite(PWMB, 0); } // Hilfsfunktionen für die Serielle Kommunikation int stoi(String s) { char char_array[s.length() +1]; s.toCharArray(char_array,sizeof(char_array)); int number = atoi(char_array); return number; } String splitString(String s, char parser, int index) { String rs='\0'; int parserIndex = index; int parserCnt=0; int rFromIndex=0, rToIndex=-1; while (index >= parserCnt) { rFromIndex = rToIndex+1; rToIndex = s.indexOf(parser,rFromIndex); if (index == parserCnt) { if (rToIndex == 0 || rToIndex == -1) { return '\0'; } return s.substring(rFromIndex,rToIndex); } else { parserCnt++; } } return rs; } void fehler() { blinkLED(ErrorLED, 2); Stop(); } //------------------------------------------------------------------------------ void setup() { Serial.begin(SERIAL_BAUD); Serial.println("Serial connection started, waiting for instructions..."); //establishContact(); // send a byte to establish contact until receiver responds //flush(); Wire.begin(); // Connects I2C for CMPS10 Compass pinMode(OdoTrig, OUTPUT); digitalWrite(OdoTrig, LOW); pinMode(leftEncoder, INPUT); pinMode(rightEncoder, INPUT); pinMode(PWMA, OUTPUT); pinMode(AIN1, OUTPUT); pinMode(AIN2, OUTPUT); pinMode(PWMB, OUTPUT); pinMode(BIN1, OUTPUT); pinMode(BIN2, OUTPUT); pinMode(STBY, OUTPUT); pinMode(motorLED, OUTPUT); pinMode(ULTRASONIC_TRIG, OUTPUT); pinMode(ULTRASONIC_ECHO, INPUT); pinMode(pingLED, OUTPUT); pinMode(ScannerServoPan, OUTPUT); pinMode(ScannerServoTilt, OUTPUT); pinMode(ErrorLED, OUTPUT); motorDriverState(HIGH); // turn driver ON Stop(); pingTimer = millis() + PING_INTERVAL; // ping starts at PING_INTERVAL ms, gives time for the Arduino to chill before starting. #ifdef DEBUG Serial.println("DEBUG: Setup finished"); #endif } // cmd: forward:255 --> vorwaerts mit pwm 255 void serialReceive() { if (Serial.available()) { dataString = Serial.readStringUntil('\n'); dataString = dataString + ":"; //needed so below works String command = splitString(dataString, ':', 0); String value = splitString(dataString, ':', 1); #ifdef DEBUG Serial.println("command: " + command + " value: " + value); #endif if (command == "forward") { ValidCommand = 1; goFWD(value.toInt()); blinkLED(motorLED, 2); } else if (command == "backward") { ValidCommand = 1; goREV(value.toInt()); blinkLED(motorLED, 2); } else if (command == "left") { ValidCommand = 1; rotateLeft(value.toInt()); blinkLED(motorLED, 2); } else if (command == "right") { ValidCommand = 1; rotateRight(value.toInt()); blinkLED(motorLED, 2); } else if (command == "stop") { ValidCommand = 1; Stop(); blinkLED(motorLED, 2); } else if (command == "ping") { ValidCommand = 1; ping(); blinkLED(motorLED, 2); } else if (command == "compass") { ValidCommand = 1; Compass(); blinkLED(motorLED, 2); } else if (command == "search") { ValidCommand = 1; ActiveMode = "Search"; blinkLED(motorLED, 2); } else if (command == "init") { ValidCommand = 1; setup(); blinkLED(motorLED, 2); } else if (command == "pan") { ValidCommand = 1; move_servo_pan(value.toInt()); blinkLED(motorLED, 2); } else if (command == "tilt") { ValidCommand = 1; move_servo_tilt(value.toInt()); blinkLED(motorLED, 2); } else { ValidCommand = 0; Serial.print("INVALID COMMAND: "); Serial.println(dataString); } if (ValidCommand == 1) { Serial.println("MOTOR: " + command + " " + value); lastcmdtime = micros(); //Zeit des letzten Kommandos lastcmd = command; //letztes ausgeführte Kommando } } } // Search: Umgebung erkunden und Map erstellen void SearchMode() { PanTilt(); Compass(); } // AutoDrive: Selbstständig durch Umgebung fahren um Ziel zu finden void AutoDriveMode() { ; } void loop() { serialReceive(); // Search: Umgebung erkunden und Map erstellen if (ActiveMode == "Search") { SearchMode(); } // AutoDrive: Selbstständig durch Umgebung fahren um Ziel zu finden if (ActiveMode == "AutoDrive") { AutoDriveMode(); } /* if (millis() >= pingTimer) { // Is it time to ping? pingTimer += PING_INTERVAL; // Set next time this sensor will be pinged. ping(); } actual = micros(); //Timeout seit dem letzten empfangenen Befehl 2Sekunden if(actual - lastcmdtime >= 2000000) { fehler(); establishContact(); } */ }
//EDIT: Bevor ich mich nun ans eigentliche Map erstellen mache muss ich erst noch für die RadEncoder Vorbereitungen treffen - um zu wissen wieviel Strecke der RoPi zurückgelegt hat.
Für eine bessere Navigation sollte man dann zudem die ungefähren Abmessungen (aufgerundet) des Roboters wissen und festlegen, was dann in der Map die Größe der Quadrate (Zelle) festlegt. Wenn also der RoPi zum Beispiel 15cm breit und 20cm lang ist, wären auch die Quadrate so groß. Erfasst er dann ein Hindernis wird das jeweilige Quadrat, was zB 60cm entfernt ist, als komplett "unbefahrbar" markiert und man läuft nicht Gefahr dagegen zu fahren.
Beim herumfahren würde er dann seine eigene Position als aktuelle RoPi-Position (Wert: 254) übermitteln und beim verlassen dieses Quadrats (Zelle) erhält dies selbstverständlich auch ein 'befahrbar' Wert von 0.
Erkennt er ein Objekt in 60cm Entfernung werden die Quadrate (Zelle) dazwischen als 'befahrbar' (Wert: 0) und das Quadrat vom 60cm entfernten Objekt als 'unbefahrbar' (Wert: 255) markiert. Mithilfe des Kompass weiß man dann auch die Richtung.
Gibt man ihm ein Ziel wird dieses mit dem Wert 1 markiert, wohin er dann selbstständig den optimalsten Weg finden muss. -
Die Servo.h ist totaler müll... die liest nicht wirklich die aktuelle Position aus sondern gibt nur den zuletzt via write() gesetzt Wert wieder
Dh wenn ich zB den Pan Servo erst auf Position 150 schicke und anschließend auf 10, kann ich nicht prüfen ob er da auch wirklich angekommen ist - bzw jenachdem wie schnell die Servos sind kanns halt öfters vorkommen das der selber festgelegte delay zu kurz ist Das nervt mich grad tierisch, vorallem weil ich keine delays nutzen will =(
Habs hiermit versucht:
Code
Alles anzeigen// manual move pan servo and detach after reaching position void move_servo_pan(int pos) { Serial.print("pos: "); Serial.println(pos); pan_ScannerServo.attach(ScannerServoPan); pan_ScannerServo.write(pos); volatile int cn = 0; do { cn++; Serial.print("cn: "); Serial.println(cn); delay(20); } while (cn < pos); delay(50); pan_ScannerServo.detach(); }
Aber wie gesagt, selbst damit kommt er nicht schnell genug von 150 auf 10... andersherum also von 10 auf 150 ist damit kein Problem da er ja mit 150 länger zählt und somit delayed
Und detachen tut er auch nicht wirklich - zZt kein Plan wieso :sIch hasse delay's - auch künstliche!
-
Die Servo.h ist totaler müll... die liest nicht wirklich die aktuelle Position aus
...
Aber wie gesagt, selbst damit kommt er nicht schnell genug von 10 auf 150
Und detachen tut er auch nicht wirklich - zZt kein Plan wieso :sevtl. doch einen Drehgeber (oder Winkeldecoder) mitlaufen lassen ? umso unabhängig von verschluckten Steps zu sein ?
Ich hasse delay's - auch künstliche!kann ich voll verstehen ! :thumbs1:
-
Wie kommst du auf Decoder?
Es geht um die Servo's die an eine bestimmte Position drehen sollen und darum festzustellen ob sie dort auch ankommen bevor die Servo's abgeschaltet werden, weil sonst die Motoren der Servos die ganze Zeit an sind und somit auch Strom verbrauchenSetze ich den Pan Servo erst auf Position 150 und anschließend auf 10, reicht der Delay nicht da er ja nur 10 * 20ms nutzt - um Gegensatz dazu wäre von 10 auf 150 eben der Delay viel höher -> 150 * 20ms. Setze ich den Delay aber höher verschwendet er Zeit weil er längst an der Position angekommen is
-
Hi alter Tüftler,
das Dumme ist, dass Servos in der Regel (zumindest die preiswerten Teile) keine Rückmeldung über ihre Position liefern.
Wie kommst du auf Decoder?
Ich hatte dato mal nach einer Möglichkeit gesucht, die reale Position festzustellen, und bin dabei u.a. auf das -> hier <- gestossen.
Das geht imho so in die Richtung wie jar das meinte ...Ich hab' das nach wie vor auf Halde ... wer weiss, ob ich das mal wirklich brauche.
cheers,
-ds- -
Nunja, das setz ich erstmal auf die ToDo Liste und mach mit anderem Krams weiter
Ich studiere grad die verschiedenen Möglichkeiten für Pathfinding da ich ja nun Softwaretechnisch bereits soweit gekommen bin das ich das in Angriff nehmen kann..
Zunächst werde ich mich wohl dazu entscheiden 2 verschiedene Maps zu nutzen:
- Eine lokale Karte im Speicher des Arduino's welche die aktuelle, unmittelbare Umgebung repräsentiert.
- Eine globale Karte die der RaspberryPI verwaltet, welche dynamisch wächst.
Bei der Verwendung von 2 Karten steigt die Genauigkeit, wie man zB auch hier nachlesen kann.
Der Abgleich beider Karten erfolgt aber nicht in Echtzeit sondern Zeitversetzt.Beim autonomen Fahren übermittelt der Arduino seine Positions- und Sensordaten ans Gehirn (RaspberryPI), welches dann die Position mit der globalen Karte vergleicht und dem Arduino (ausführendes Organ) unter Umständen sagt dass da früher ein mal ein Hindernis war und der RoPi somit "vorsichtiger" fahren soll..
Ich werde zudem die bereits erwähnten Zellen Werte (0, 1, 254, 255) um einige erweitern, wie zum Beispiel für einen Abgrund/Loch auf einen negativen Wert der sich nicht ändern lässt, oder auch für Wände die ebenfalls nicht einfach so verschwinden
Befährt der RoPi dann einen Bereich den das Gehirn bereits kennt (globale Karte), sollten die Werte der Zellen in der globalen Karte für die Anzahl der wiederholten Abtastung immer weiter "stabilisiert" werden -> befährt er zum ersten mal einen Raum und es wird eine Wand erfasst, erhällt diese zum Beispiel erst einmal nur den Wert 200. Befährt er den Raum dann später nochmal und erfasst die selbe Wand erneut wird der Wert für diese Zelle auf zB 100 gesetzt, solange bis die Zelle einen negativen und nicht veränderbaren Wert von zB -100 erreicht... Hat eine Zelle einen negativen Wert brauch sich der RoPi damit auch nicht weiter beschäftigen sondern weiß dass das Objekt statisch immer da istNun hab ich verschiedene Anlaufstellen wo ich den Code studieren kann, unter anderem direkt auf der OpenSLAM Seite wo auch andere Projekte mit Code verlinkt sind. Aber auch das gut Dokumentierten c't-Bot Wiki wo man auch Quellcode findet.
Hab dazu auch noch hier ne Seite gefunden wo auch der Code veröffentlicht wurde, da sieht man auch schon mal wie es ungefähr aussehen könnte.Allerdings stoße ich jetzt auf 2 blöde Probleme:
- Ich hab bereits jetzt 18 der verfügbaren 19 Pins des Arduino-UNO's belegt, werde für Pathfinding aber weitere Pins benötigen da ich noch mindestens 4 IR-Sensoren benötige (rund herum angeordnet wo die Reichweite auch nicht so hoch sein muss) und optimal wären (wie ich schon mal erwähnte) auch noch 2 weitere Ultraschall Sensoren da der Pan&Tilt auf Dauer zu langsam schwenkt.
- Die Arduinos haben zu wenig Ram/Cache um temporäre Werte zu speichern dh um so mehr veränderbare Variablen dazu kommen, um so mehr Ram wird belegt und genau da stoße ich sehr schnell an die Grenzen..
Wegen 2. müsste ich mir SpiRAM zulegen - und da ich bereits jetzt keine Pins mehr frei hab bzw die SPI Pins bereits verwendet werden, muss ich: Wegen 1. auf einen Arduino-Mega-2560 ausweichen.
(ein SD Shield könnte zwar auch eine Möglichkeit sein allerdings wären die Zugriffe wesentlich langsamer und ist daher eher ungeeignet für dieses Vorhaben)Der schon mal erwähnte Wavefront Algorithm wird auch im c't-Bot Wiki nochmal beschrieben. Habe dazu dann auch im dortigen Source ein bisschen gestöbert und interessanten Code gefunden:
http://www.heise.de/ct/projekte/ma…ehaviour_scan.c
http://www.heise.de/ct/projekte/ma…r_pathplaning.c
http://www.heise.de/ct/projekte/ma…t/include/map.h
http://www.heise.de/ct/projekte/ma…le/ct-Bot/map.cEin interessantes Code Beispiel für Wavefront hab ich auch hier gefunden.
Vielleicht kann ich auch die quelloffene c't-Sim für meine Zwecke missbrauchen - mal gucken
ROS hätte für sowas auch ein Module, allerdings hab ich ROS beim letzten Versuch nicht installiert bekommen und will auch erst mal ohne ROS auskommen.
(ROS install howto on RPI: hier bzw hier) -
Hey meigrafd,
schau mal, was ich -> hier <- entdeckt habe.
Wäre das evtl. eine Alternative zum Uno?cheers,
-ds- -
Hey meigrafd,
schau mal, was ich -> hier <- entdeckt habe.
Wäre das evtl. eine Alternative zum Uno?happige Preise, was ist da besser als Arduino Nanos 328p (32k flash) für 5€ oder Mega2560 (256k flash) für 12,50 ?
-
Ja ich glaub der Teensy fällt flach, der ist mir zu teuer Also wenn dann käm für mich nur der Teensy++ 2.0 für $24 in frage.
Einen Arduino-Mega2560 R3 kriegt man in der Bucht bereits für 15€ inkl. VSK (oder aus China für 10€)Ein Arduino NANO und Pro Mini hab ich auch noch hier, aber die haben auch zu wenig I/O's.
Beim Mega2560 ist halt auch ein 4kB großer EEPROM drauf den man mit der gleichnamigen Lib lesen/beschreiben kann und dessen Inhalt auch nach PowerOff bestehen bleibt. Dadrin könnte man ggf die Maps bzw den letzten Zustand auch hinterlegen.
Heute mach ich mich erst mal ans Regelwerk und muss mir hierfür eine flexible Methode ausdenken die Rules nicht hardcoded im python Script festzulegen (ich mag kein hardcoded :D).
-
Hi,
ich buddle gerade mal wieder in den Tiefen des WWW und suche Anregungen, Ideen, Impulse, ...
Da kam mir eine Idee: Du sagst ja, dass Dir die µC zu wenig IOs haben ... könntest Du das Problem nicht mit z.B. einem MCP23008 lösen? Die Arduinos, selbst der Pro Mini, können ja I2C und diesen Baustein gäbe es ja auch als SPI Variante (MCP23S0).
Wie gesagt ... nur so eine Idee, aber evtl. reicht Dir das ja ...cheers, ich geh weitergraben,
-ds- -
ich buddle gerade mal wieder in den Tiefen des WWW und suche Anregungen, Ideen, Impulse,wenn es einen Arduino o.ä. als mini oder micro gäbe mit mega1284p das wäre was
klein TSOP 44 Pin
Flash (Kbytes): 128 Kbytes
SRAM (Kbytes):16
EEPROM (Bytes):4096
Operating Voltage (Vcc):1.8 to 5.5
UART: 2
PWM Channels: 6
Diff. ADC Inputs: 14 (genial für Strom & Spannungsmessung ! )http://www.atmel.com/devices/atmega1284p.aspx?tab=parameters
also ich mag den, als DIL 40 oder TSOP 44 ATmega32 kompatibel !
-
Hi Berliner ...
...
wenn es einen Arduino o.ä. als mini oder micro gäbe mit mega1284p das wäre was
...
hm ... kann man dem nicht einfach den Arduino Bootloader verpassen?
Ich muss dazu sagen, ich hab noch nie einen AVR direkt per Bootloader zum Arduino umgeflasht ... sollte aber gehen.
Werd' ich mal im Hinterkopf behalten. Das interessiert mich und evtl. finde ich eine funktionierende Anleitung dazu.
Ich würd' das ja auch so mal probieren, aber ich hab' da immer Sorgen wegen den Fuses ... das wäre nicht der erste µC den ich aufgrund falsch gesetzter Fuses in die ewigen Jagdgründe geschickt hätte ...
see you, "Der mit dem heissen Eisen winkt" ... (in Anlehnung an "Der mit dem Wolf tanzt") ...
-ds- -
hm ... kann man dem nicht einfach den Arduino Bootloader verpassen?
Ich muss dazu sagen, ich hab noch nie einen AVR direkt per Bootloader zum Arduino umgeflasht ... sollte aber gehen.dann fehlt immer noch die USB Anbindung ! CH340 oder FTI oder Mega8
die einzige Platine die das bieten würde hat einen m32 IMHO aber den runterlöten ist Quark .....
-
tut mir leid das ich hier nochmal störe aber wer Aruinos einsetzt und günstig sollte folgendes noch wissen:
es gibt nun mindestens 3 USB Anbindungen:
mit ATmega8 Treiber in der Arduino IDE vorhanden,
mit FTI, kenne ich nicht,
Nano mit CH340 habe ich für 5 € aus China bekommen, brauchen wieder extra Treiber, nach mehr graue Haare und viel googeln gefunden:
http://www.jens-bretschneider.de/aktuelle-treib…zu-usb-adapter/
jetzt laufen die 5€ Teile aber prima .... -
Ach für Windows ... wer nutzt denn so was
-ds- -
Ach für Windows ... wer nutzt denn so wasach du programmierst Arduino am PI ? :s
wie geht das ? ist der nicht ein bissl lahm ?
oder hast du das durchgestrichene OS ?
-
Jetzt mitmachen!
Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!