Page 1 of 1

Gertbot DCC Python example

Posted: Tue Jun 30, 2015 11:08 pm
by mike21724
Very nice unit - but I am having a major mental blockage on getting it working utilizing the Python library provided. Has anyone got the basics going using pure Python? Forward, back etc, once I have that I will work the rest out.

Thanks

Re: Gertbot DCC Pyhton example

Posted: Wed Jul 01, 2015 8:17 am
by Gert van Loo
At the bottom of this page: http://www.gertbot.com/download.html
there is a python example: http://www.gertbot.com/gbdownload/src/py_rover.tgz
It is for two brushed motors.
Is that the one you are using?

p.s. I corrected the typo in the title to make it easier for others to find.

Re: Gertbot DCC Python example

Posted: Wed Jul 01, 2015 3:07 pm
by mike21724
I'm trying to do DCC. Used the rover to get some basics stuff going (UART etc) but now I'm up to trying to send it a DCC command and I'm not sure of the structure.
Do we send preamble, the DCC decoder address is included in the data packet etc...

Thanks
Mike

Re: Gertbot DCC Python example

Posted: Wed Jul 01, 2015 3:36 pm
by Gert van Loo
I am at work and have a better look later.

If I remember:
To send a DCC command you put all the standard DCC data in a array and send it to a board and to a channel.
Simplest is to send it to ALL channels. (Channels which are not in DCC mode will just ignore the command)

the python arguments are: send_dcc_mess(board,channel,data)
I hope you know what your board ID is set to.
For channel use 0x0F.
To send a stop command fill data with two values: the locomotive number and the stop command.
e.g. Loc = 0x03 and stop = 0x40
The 'send_dcc_mess' routine will do the rest.

Re: Gertbot DCC Python example

Posted: Thu Jul 02, 2015 5:13 pm
by Gert van Loo
Sorry, yesterday was gone before I realized it.
I have unearthed some Python code I used to test the DCC.

Code: Select all

   board = 0
   print("DCC test on board %d\n" % board)
   for chan in range(0,4) :
     gb.set_mode(board,chan,gb.MODE_DCC)
     
   print("Performing number of writes\n")
   message = [0x03, 0x68 ]
   print("0x03,0x68: move loc 3. Press return to send")
   input()
   gb.send_dcc_mess(board,0xF,message)
   
   message = [0x02, 0x67 ]
   print("0x02,0x67: move loc 2. Press return to send")
   input()
   gb.send_dcc_mess(board,0xF,message)

   message = [0x00, 0x40 ]
   print("0x00,0x40: Stop All. Press return to send")
   input()
   gb.send_dcc_mess(board,0xF,message)

Re: Gertbot DCC Python example

Posted: Thu Jul 02, 2015 5:38 pm
by mike21724
Awesome thanks, I am familiar with those days.

I reread the spec last night (that's a great way to get to sleep) and I think the critical point was that each thing that you want the train to do is a separate packet. So turn light on and go x speed are different packets.
The way the spec is written, or I read it, it takes a deep dive to determine that.
I'll test today and let you know how it goes.

Mike

Re: Gertbot DCC Python example

Posted: Thu Jul 02, 2015 10:12 pm
by mike21724
Hi Gert - got it working sort of.

Here's whats happening.
Track is connected to channel 0
If I run the python code (below) - I get an error and nothing happens.
ERROR Enable 0 was negated.

Move the track to channel 1.
ERROR Enable 1 was negated.

However if I run the Raspbian gb_dcc GUI then the train gets power to it's track (so can't be a short or anything).
Then if I run the python code I get no errors and the train moves as programmed.

Any suggestions?

Code: Select all

import gertbot as gb
import curses
import time

BOARD       = 0         # Which board we talk to
PHY_CHANNEL = 0          # channel for  track
LOCO        = 0x04
gb.open_uart(0)

#gb.set_mode(BOARD, PHY_CHANNEL, MODE)

print("DCC test on board %d\n" % BOARD)
for chan in range(0,4) :
 gb.set_mode(BOARD,chan,gb.MODE_DCC)

print ("ERROR" , gb.error_string(gb.read_error_status(BOARD)))
print ("MOTOR CONFIG " , gb.get_motor_config(BOARD, 0))


print("Performing number of writes\n")
message = [0x04, 0x63 ]
print("0x04,0x68: move loc 4. Press return to send")
input()
gb.send_dcc_mess(BOARD,0xF,message)

Re: Gertbot DCC Python example

Posted: Fri Jul 03, 2015 7:35 am
by Gert van Loo
You are right!
I could not remember the details but I had a recollection that I also saw the enables activating.
I just went into the C-GUI code and found this:

Code: Select all

  case MOT_MODE_DCC:
    // First switch channel short circuit to off
    uart_tx(CMD_STOPSHORT,id,ENDSTOP_OFF|ENB_ERR_IGNORE); // No short no endstops 
    // DCC mode  
    uart_tx(CMD_OPMODE,id,mode);
Just as a note: the short circuit protection is never switched off completely.
You just switch off that the CPU disables the channel.

I have to update the python drivers to include that.

Re: Gertbot DCC Python example

Posted: Fri Jul 03, 2015 2:55 pm
by mike21724
Thanks, I'll test and let you know.

Mike

Re: Gertbot DCC Python example

Posted: Mon Jul 06, 2015 5:51 pm
by mike21724
I added the three missing globals and then used send_raw to transmit them. I still get the "Enable 1 was negated" message but the train moves.

Code: Select all

ENB_ERR_IGNORE = 0x00
CMD_START_VAL  = 0xA0  # Serial protocol start flag
CMD_STOP_VAL   = 0x50  # Serial protocol end flag

print("DCC test on board %d\n" % BOARD)
for chan in range(0,4) :
 message = []                                      
 gb.ENDSTOP_OFF | ENB_ERR_IGNORE, CMD_STOP_VAL)
 message.append(CMD_START_VAL)                      
 message.append(gb.CMD_STOPSHORT)                   
 message.append((BOARD<<2) | chan)                  
 message.append(gb.ENDSTOP_OFF | ENB_ERR_IGNORE)    
 message.append(CMD_STOP_VAL)                       

 gb.send_raw(message)
 gb.set_mode(BOARD,chan, gb.MODE_DCC)


Re: Gertbot DCC Python example

Posted: Fri Jul 24, 2015 5:23 pm
by mike21724
Hey Gert,

This was working and now it's stopped with a weird message:

('ERROR', 'Illegal error status code')
('MOTOR CONFIG ', [])

Dumbed down the code to minimum and still failing. Not sure what the message means:

Code: Select all

ENB_ERR_IGNORE = 0x00
CMD_START_VAL  = 0xA0  # Serial protocol start flag
CMD_STOP_VAL   = 0x50  # Serial protocol end flag
for chan in range(0,4) :
  message = []
  #gb.send_raw(gb.ENDSTOP_OFF | ENB_ERR_IGNORE, CMD_STOP_VAL)
  message.append(CMD_START_VAL)
  message.append(gb.CMD_STOPSHORT)
  message.append((BOARD<<2) | chan)
  message.append(gb.ENDSTOP_OFF | ENB_ERR_IGNORE)
  message.append(CMD_STOP_VAL)
  gb.send_raw(message)
  gb.set_mode(BOARD,chan, gb.MODE_DCC)

print ("ERROR" , gb.error_string(gb.read_error_status(BOARD)))
print ("MOTOR CONFIG " , gb.get_motor_config(BOARD, 0))

Re: Gertbot DCC Python example

Posted: Fri Jul 24, 2015 5:46 pm
by Gert van Loo

Code: Select all

Dumbed down the code to minimum and still failing. Not sure what the message means:
Most likely an error in the driver.
I get an error number from the board "gb.read_error_status(BOARD)"
Then I look that up in set of strings. "gb.error_string(...)"
If the error number is outside the sets of strings the program will fail.

Please print out the error number only. So what is the value of "gb.read_error_status(BOARD)".
Then I can have a look in the code and see what the actual error is.

Re: Gertbot DCC Python example

Posted: Fri Jul 24, 2015 5:55 pm
by mike21724
print ("ERROR STRING" , (gb.read_error_status(BOARD)))

returns -1

Re: Gertbot DCC Python example

Posted: Fri Jul 24, 2015 9:04 pm
by Gert van Loo
OK, that suggest the gb.read_error_status call failed.
The board returned garbage or nothing at all.
See the python driver code below.

Code: Select all

#
# Return error status of board
# (zero means no pending errors)
# (-1 means read error)
def read_error_status(board):
   # To do : check the arguments
   dest = board<<2
   wrtbuf = [PRE, CMD_GET_ERROR, dest, POST, POST, POST, POST]
   os.write(filehandle,bytes(wrtbuf))
   termios.tcdrain(filehandle)
   ok , data = read_uart(4)
   if (not ok) : 
     return -1
   val = (data[2]<<8) | data[3]
   return val
It also explains the error text you are seeing.
The gb.error_string code reports "Illegal error status code" for any code outside the expected range:

Code: Select all

...
"DCC illegal message (length)",                   # ERROR_DCC_MESS     0x0020 
"Illegal error status code"  )                    # MAX_ERROR

def error_string(error_number):
  if (error_number<0 or error_number>MAX_ERROR):
    error_number = MAX_ERROR
  return error_text[error_number]

I can't say why there is a read error.
Most likely the return data stream got out of sync.
That is: one or two bytes got lost.
I have no good solution to prevent that.

Re: Gertbot DCC Python example

Posted: Sun Jul 26, 2015 3:34 pm
by mike21724
hey Gert,

Thanks for the help. Did some hardware troubleshooting and after swapping the Pi it started working again, grrr...

Mike

Re: Gertbot DCC Python example

Posted: Tue Nov 24, 2015 7:54 pm
by mike21724
My adventure continues...

Working great so far BTW. I have now built a RESTFul API that controls the train via the GertBot.

My next question is about power.

I need to pull more than the 2.5a from the track (closer to 5-6a). Reading the docs I was a little confused as there seems to be 2 options (one untested).

Option 1 seems to be to sync the control signals and then parallel out the outputs.
Option 2. Is untested.

What would you recommend?