#!/usr/bin/python # HAL userspace component to interface with Arduino board # Copyright (C) 2015 Marius Liebenberg # # This program and accompanied works are provided as is and the # author will not be liable for anything whatsoever related to # this software or not. # # This user space program will allow you to connect to an Arduino # UNO, or the likes of, that is fitted with a network shield. I am # other boards will work as well with a bit of adaptation to the embedded # code. # # The arduino configuration is as follows: # Analog Outputs - 1 at pin 3 # Analog Inputs - 6 at pins A0 to A5 # Digtal pins: - 6 in total configured as In or OUT at startup # Encoder - pins 8 and 9 are used for the MPG encoder. Make # sure the pins are set as inputs. That means you # cannot have six outputs if you use the encoder. # # Note: The mpg-count-00 is the previous count and mpg-count-01 is the new count # # Usage: loadusr -W /yourdir/udps NIC_IP NIC_PORT REMOTE_IP REMOTE_PORT number_of_ouputs # loadusr -W ~/bin/udps 192.168.16.10 8888 192.168.16.200 8888 1 # # I have used this on a second network interface as well as a USB plugin ethernet # adapter hence the need to provide the local IP details. # # Use the Arduino code udpcomms.ino in conjunction with this program. # # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #import serial import os import hal import sys import time import socket from gwibber.microblog.can import RECEIVE from _socket import SOL_SOCKET from IN import SO_BINDTODEVICE data = " " REMOTE, R_PORT = "192.168.16.200", 8888 if len(sys.argv) > 4: HOST = sys.argv[1] H_PORT = int(sys.argv[2]) REMOTE = sys.argv[3] R_PORT = int(sys.argv[4]) print ("HOST = ", HOST) print ("PORT = ", H_PORT) print ("REMOTE = ", REMOTE) print ("PORT = ", R_PORT) if len(sys.argv) > 4: nout = int(sys.argv[5]) else: nout = 6 print ("Number of digital outputs = ", nout) if nout > 6 or nout < 0: print "##########################################################################################" print "Usage: loadusr -W /yourdir/udps NIC_IP NIC_PORT REMOTE_IP REMOTE_PORT number_of_ouputs " print "##########################################################################################" raise SystemExit, "Number of digital outputs must be from 0 to 6" pinmap = [4,5,6,7,8,9] # Encoder can be connected to 8 and 9 dacpinmap = [3] # DAC fixed c = hal.component("udpio") c.newpin("analog-out-%02d" % dacpinmap[0], hal.HAL_FLOAT, hal.HAL_IN) c.newparam("analog-out-%02d-offset" % dacpinmap[0], hal.HAL_FLOAT, hal.HAL_RW) c.newparam("analog-out-%02d-scale" % dacpinmap[0], hal.HAL_FLOAT, hal.HAL_RW) c['analog-out-%02d-scale' % dacpinmap[0]] = 1.0 for port in range(6): c.newpin("analog-in-%02d" % port, hal.HAL_FLOAT, hal.HAL_OUT) c.newparam("analog-in-%02d-offset" % port, hal.HAL_FLOAT, hal.HAL_RW) c.newparam("analog-in-%02d-gain" % port, hal.HAL_FLOAT, hal.HAL_RW) c['analog-in-%02d-gain' % port] = 1.0 for port in range(nout): c.newpin("digital-out-%02d" % pinmap[port], hal.HAL_BIT, hal.HAL_IN) c.newparam("digital-out-%02d-invert" % pinmap[port], hal.HAL_BIT, hal.HAL_RW) for port in range(nout, 6): c.newpin("digital-in-%02d" % pinmap[port], hal.HAL_BIT, hal.HAL_OUT) c.newpin("digital-in-%02d-not" % pinmap[port], hal.HAL_BIT, hal.HAL_OUT) c.newparam("digital-in-%02d-pullup" % pinmap[port], hal.HAL_BIT, hal.HAL_RW) c.newpin("network-error", hal.HAL_BIT, hal.HAL_IN) for i in range(2): c.newpin("mpg-count-%02d" % i, hal.HAL_FLOAT, hal.HAL_IN) c.ready() data = " ".join(sys.argv[3:]) firstbyte = 0 state = 0 txbuf = range(6) rxbyte = 0 analogout = range(1) analogin = range(6) dout = 0 invert = 0 din = 0 pullup = 0 v = 0 count = 0 soh = "#" service = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) service.bind((HOST, H_PORT)) service.settimeout(1) print "listening on port", R_PORT ############################################################### # RECEIVE # ############################################################### def doRx(): try: received = service.recv(150) except IOError: c['network-error'] = 1 else: c['network-error'] = 0 workbuf = (received) tokens = [int(x) for x in workbuf.split(',') if x.strip()] for i in range(6): gain = c['analog-in-%02d-gain' % i] offset = c['analog-in-%02d-offset' % i] value = (int(tokens[i]) & 1023) / 1023. * 5.0 * gain + offset c['analog-in-%02d' % i] = value dig = int(tokens[6]) for i in range(nout,6): msk = (1 << i) v = (dig & msk) if(v > 0): c['digital-in-%02d' % pinmap[i]] = 1 c['digital-in-%02d-not' % pinmap[i]] = 0 else: c['digital-in-%02d' % pinmap[i]] = 0 c['digital-in-%02d-not' % pinmap[i]] = 1 for i in range(7,9): c['mpg-count-%02d' % (i-7)] = (tokens[i]) return ################################################################ # TRANSMIT # ################################################################ def doTx(): for state in range(1): scale = c['analog-out-%02d-scale' % dacpinmap[state]] or 1. offset = c['analog-out-%02d-offset' % dacpinmap[state]] data = int((c['analog-out-%02d' % dacpinmap[state]] - offset) / scale) if data < 0: data = 0 if data > 255: data = 255 analogout[state] = data #6 bytes of analog out data data = 0 txbuf[state + 1] = analogout[state] dout = 0 pullup = 0 for state in range(6): if state < nout: if ( c['digital-out-%02d' % pinmap[state]]) == 1: if (not c['digital-out-%02d-invert' % pinmap[state]]): dout |= (1 << state) else: dout |= (0 << state) else: if (not c['digital-out-%02d-invert' % pinmap[state]]): dout |= (0 << state) else: dout |= (1 << state) else: if ((c['digital-in-%02d-pullup' % pinmap[state]]) == 1): pullup |= (1 << state) txbuf[2] = (nout) txbuf[3] = (dout) txbuf[4] = (pullup) txbuf[5] = '~' txbuf[0] = soh service.sendto(format(txbuf), (REMOTE, R_PORT)) #time.sleep(0.02) ################################################################ # MAIN LOOP # ################################################################ if __name__ == "__main__": try: while 1: doTx() doRx() except (KeyboardInterrupt,): raise SystemExit, 0