Shop OBEX P1 Docs P2 Docs Learn Events
Eddie Control via Linux system — Parallax Forums

Eddie Control via Linux system

Julierme AraJulierme Ara Posts: 3
edited 2012-09-03 23:41 in Robotics
The intent in my project is to obtain and send information to the control board Eddie through a Linux system. No need to use Microsoft Robotics Developer Studio 4 (RDS4).


Typically, in the windows, would use a driver and/or a library of functions to make the USB connection to a control board.
In Linux, how will this connection?
Could someone give me a hint or point to a path?

Thank you for listening.

Comments

  • Julierme AraJulierme Ara Posts: 3
    edited 2012-07-26 12:35
    Note:
    - Linux version: Ubuntu 10.04;
    - Linux running on a notebook;
  • Julierme AraJulierme Ara Posts: 3
    edited 2012-07-28 10:44
    Thank Cravado.
    This is a drive to be studied.
    I will also be looking at other possibilities.
  • Jay.BeaversJay.Beavers Posts: 7
    edited 2012-09-03 13:22
    The Eddie Control Board is a USB device that appears to a laptop as a CDC (Communications Device Class) device. On Windows, this becomes a 'virtual com port', on Linux this becomes something like /dev/ttyACM0. I haven't played around with the specifics of the Eddie but you should be able to find the matching device from there.

    Once you have the name of the COM port, Eddie is controlled via some simple text messages called the Eddie Command Set which are easy to parse which are documented in the linked PDF. You can write your own 'driver' for Eddie by talking to the COM port and sending/receiving these messages.

    You'll still have to find yourself a programming environment on Linux that supports talking to the COM port. You have a couple of choices, such as C/C++, nodejs, or python.
  • SRLMSRLM Posts: 5,045
    edited 2012-09-03 23:41
    On Ubuntu, the FTDI based devices appear as a serial port at /dev/ttyUSB*

    I've attached a file that uses Python to connect to the serial port. It's a little messy, but shows a simple and cross platform programatic access method.

    Here is how I develop for the Propeller on Ubuntu, if it helps: http://forums.parallax.com/showthread.php?140139-Gedit-Spin-Syntax-Highlighting-gt-Solution!&p=1098762#post1098762
    #!/usr/bin/python
    
    #TODO Find out why there is a 1 being sent through serial
    
    
    from threading import Thread
    from threading import Lock
    import time
    import serial
    import platform
    import threading
    
    
    ser = None
    rx_buffer_lock = Lock()
    rx_buffer = []
    thread = Thread()
    #last_received = ''
    
    
    
    class RxParser(object):
    	def  match(self, line, code):
    		# Line is the received line from the rx_buffer
    		# code is the string type that you want to match against, eg "$ADRPS" or "$ADMIA"
    		original_line = line
    		if line.find(code) != -1: #String matches
    			line = line[len(code)+2:] #Get rid of found string. +2 to account for space and to get to next char
    			nums = line.split(",")
    			if len(nums) > 5:
                                    print "Bad datal. Too many fields."
                                    return []
    			try:
    				for i in range(len(nums)):
    					if i != 0: #Get rid of clock (for now, debug)
    					#	nums[i-1] = float(nums[i-1])
    					# TODO: FIX THIS TO ENABLE TIMING
    						nums[i-1] = float(nums[i])
    				nums.pop() #Get rid last (non converted) string element (since the first space was occupied by the clock, but now holds a variable value)
    			except ValueError:
    				print "RxParser: Could not parse ", code, " String. RX Line: ", original_line
    				return []
    			
    			
    			return nums
    		else:
    			return []
    
    #	def ADRPS(self, line):
    #		#Returns a list with the motor speeds, or an empty list
    #		if line.find("$ADRPS ") != -1: #String matches
    #			line = line[8:] #Get rid of found string
    #			nums = line.split(",")
    #			try:
    #				for i in range(len(nums)):
    #					nums[i] = float(nums[i])
    #			except ValueError:
    #				print "Could not parse $ADRPS String"
    #				return []
    #			
    #			return nums
    #		else:
    #			return []
    #	def ADMIA(self, line):
    #		#Returns a list with the motor currents, or an empty list
    #		if line.find("$ADMIA ") != -1: #String matches
    #			line = line[8:] #Get rid of found string
    #			nums = line.split(",")
    #			try:
    #				for i in range(len(nums)):
    #					nums[i] = float(nums[i])
    #			except ValueError:
    #				print "Could not parse $ADMIA String"
    #				return []
    #			
    #			return nums
    #		else:
    #			return []
    
    
    def receiving(ser):
    	global rx_buffer
    	global threadkillall
    #	global threadkillall
    	
    	buffer = ''
    #	while not threadkillall:
    	while True:
    		buffer = buffer + ser.read(ser.inWaiting())
    		if '\n' in buffer:
    			lines = buffer.split('\n') # Guaranteed to have at least 2 entries
    #			print "len(lines) == ", len(lines)
    			if not rx_buffer_lock.acquire(False):
    #				print "Could not get lock..."
    				pass
    			else:
    #				print "Got lock..."
    				try:
    					for i in range(len(lines)-1):
    						rx_buffer.append(lines[i])
    #					last_received = lines[-2]
    				finally:
    					rx_buffer_lock.release()
    			#If the Arduino sends lots of empty lines, you'll lose the
    			#last filled line, so you could make the above statement conditional
    			#like so: if lines[-2]: last_received = lines[-2]
    			buffer = lines[-1]
    		else:
    			time.sleep(.01)
    	print "closing..."
    	ser.close()
    
    def sending(ser, command):
    	global rx_buffer
    	global threadkillall
    	#whatwas = 1
    
    	#sersend.open()
    	print ser.isOpen()
    	print ser.portstr
    	print str(command) + "\n"
    	
    	ser.write(str(command)+ "\n")
    	whatwas=2
    	#ser.write("hello")
    	whatwas=3
    	time.sleep(.01)
    	print whatwas
    
    
    class DataGen(object):
    	def __init__(self, init=50):
    		try:
    			if platform.system() == 'Windows':
    				global ser
    				ser = serial.Serial(
    					port = 'COM24',
    					baudrate=115200,
    #					bytesize=serial.EIGHTBITS,
    #					parity=serial.PARITY_NONE,
    #					stopbits=serial.STOPBITS_ONE,
    #					timeout=0.1,
    #					xonxoff=0,
    #					rtscts=0,
    #					interCharTimeout=None
    			)
    			else:
    				global ser
    				ser = serial.Serial(
    #					port = '/dev/ttyUSB0',
    					port = '/dev/ttyACM0',
    					baudrate=115200,
    #					bytesize=serial.EIGHTBITS,
    #					parity=serial.PARITY_NONE,
    #					stopbits=serial.STOPBITS_ONE,
    #					timeout=0.1,
    #					xonxoff=0,
    #					rtscts=0,
    #					interCharTimeout=None
    			)
    		except serial.serialutil.SerialException:
    			#no serial connection
    			ser = None
    			print "NO Serial Connection! Check Serial Port! Closing."
    		else:
    			thread2 = threading.Thread(target=sending, args=(ser,'',)).start()
    			thread = threading.Thread(target=receiving, args=(ser,)).start()
    			
    		
    #	def next(self):
    #		if not self.ser:
    #			return 100 #return anything so we can test when Propeller isn't connected
    #		#return a float value or try a few times until we get one
    #		return 50
    #		
    #		for i in range(40):
    #			raw_line = last_received
    #			try:
    #				return float(raw_line.strip())
    #			except ValueError:
    #				print 'bogus data',raw_line
    #				time.sleep(.5)
    #		return 0.
    
    
    
    
    def cleanup():
    	print "Ending and cleaning up"
    	thread.exit()
    
    
    if __name__=='__main__':
    	print "Please note this is not intended to be run standalone. Please run ./anzhelka_terminal_gui.py instead."
    	s = DataGen()
    	while True:
    		time.sleep(.015)
    		print s.next()
    
Sign In or Register to comment.