[Linuxtrent] Re: [OT?] Pololu maestro

  • From: Antonio Galea <antonio.galea@xxxxxxxxx>
  • To: linuxtrent <linuxtrent@xxxxxxxxxxxxx>
  • Date: Mon, 3 Mar 2014 20:52:35 +0100

2014-03-03 14:12 GMT+01:00 Daniele Zambelli <daniele.zambelli@xxxxxxxxx>:
>
> Il problema nasce con il software MaestroControlCenter (MCC) che eseguo con:
> $> mono MaestroControlCenter
> Presenta diverse schede e permette di definire diversi "frame" (posizioni dei 
> vari servo) e di farli eseguire in sequenza.
> L'ultima scheda, "script" visualizza il programma creato da MCC. Permette di 
> eseguirlo, di eseguirlo passo passo, di fermarlo.
> Ora, quando tento di modificare il programma realizzato automaticamente da 
> MCC i bottoni che permettono il controllo
> dell'esecuzione vengono disattivati.
> Tutti i miei caotici tentativi di modificare uno script e di eseguirlo sono 
> stati frustrati miseramente. E non riesco a capire a quale
> livello (installazione software, permessi, interfaccia, sintassi, ...) si 
> trovi il problema.

Ok, stai usando il software fornito da Pololu. Nonostante sia fatto
bene, sfortunatamente è in C# - il supporto Linux offerto da Mono non
è grandioso (per essere molto generosi).

> Se però è possibile programmare in Python la scheda allora lascio perdere il 
> Forth.
> Potresti darmi qualche indicazione in proposito?

I comandi via seriale sono facili da implementare. Ti allego uno
script Python di esempio, così ti fai un'idea della semplicità. Non ho
provato a farmi un compilatore per il linguaggio di script, ma credo
non sia troppo difficile avendo la documentazione del bytecode.

Antonio
#!/usr/bin/python -u
# -*- coding: utf8 -*-

import serial, time, sys

class PololuMaestroServoController:
  def __init__(self,dev):
    self.dev  = dev
    self.ser  = serial.Serial(self.dev)
    self.addr = 0x0C
  def __del__(self):
    self.ser.close()
  def send(self,cmd):
    command = ''.join(map(chr,[0xAA,self.addr]+cmd))
    self.ser.write(command)
  def recv(self,n):
    return map(ord,self.ser.read(n))
  def setTarget(self,channel,target): #pulse width in 1/4 of microsecond
    if 0 <= target <= 8192:
      self.send([0x04,channel, target & 0x7F,target >> 7])
  def getPosition(self,channel):
    self.send([0x10,channel])
    ans = self.recv(2)
    return (ans[1]<<8)+ans[0]
  def goHome(self):
    self.send([0x22])
  def getErrors(self):
    bits = {
      0: 'Serial Signal Error',
      1: 'Serial Overrun Error',
      2: 'Serial RX buffer full',
      3: 'Serial CRC error',
      4: 'Serial protocol error',
      5: 'Serial timeout error',
      6: 'Script stack error',
      7: 'Script call stack error',
      8: 'Script program counter error',
    }
    self.send([0x21])
    err = self.recv(2)
    err = (err[1]<<8)+err[0]
    ans = []
    for b,msg in bits.items():
      if err & (1<<b): ans.append(msg)
    return ans

ch = int(sys.argv[1])
msc = PololuMaestroServoController('/dev/ttyACM0')
errors = msc.getErrors()
msc.goHome()
if errors:
  print 'ERRORS: ', ', '.join(errors)
  sys.exit(1)
for pulse in range(1500,2001,25):
  msc.setTarget(ch,pulse*4)
  print '*',
  time.sleep(.1)
print ''
time.sleep(1)
msc.goHome()
time.sleep(1)
for pulse in range(1500,999,-25):
  msc.setTarget(ch,pulse*4)
  print '*',
  time.sleep(.1)
print ''
time.sleep(1)
msc.goHome()

Other related posts: