FumblePi
Posts: 6
Joined: Mon Dec 21, 2015 6:06 pm
Location: In a Galaxy Far far away ...

I2C bit banging question/request

Mon Dec 21, 2015 7:46 pm

Good evening Raspbafarians,
I'd just like to apologise in advance if my question seems simple or at all out of place... I'm very new to the raspberry pi, and physical computing, but I’m enjoying it immensely (apart from the occasional frustrating blip--- largely due to my own professional background which is biological in nature).
I'm trying to get my T'rex motor driver to work with my Raspberry pi2. I have it connected through I2C with the RPi2 as a master and the (Arduino nano based) T'rex as a slave.
I've successfull set up the connection and am able to read the T'rex off the I2C bus with :

Code: Select all

[email protected] ~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- 07 -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
My problem occurs after sending repeated commands to the T'rex. I keep getting the following :

Code: Select all

Traceback (most recent call last):
  File "teerx.py", line 135, in <module>
    bus.write_i2c_block_data(address, 15, Pi_package)
IOError: [Errno 5] Input/output error
After reading a very long discussion about the I2C hardware/software issues with the RPi, I gathered that perhaps my device was hanging because of one of the issues mentioned in the I2C discussion (I thought ---clock stretching---, but having no specialised equipment to test this, I decided to try everything). I attempted to slow down the Raspberry's I2C Clock by doing:

Code: Select all

sudo bash -c "echo options i2c_bcm2708 baudrate=9600 > /etc/modprobe.d/i2c.conf"
It worked for about 5 or 6 button presses.
I'm now wondering if perhaps it was the code on the arduino. So I simplified it somewhat which worked for a while, then gave me the same error as above.

I've tried to learn a little about bit banging the I2C... Which quite frankly is beyond me, but am willing to attempt it (haven't given up yet). I've tried to find methods (that I can understand) that can implement it with little luck...

So my question is :
Is there a simple way to bit bang the same I2C pins (#3,5) on the raspberry pi to allow them to have clock stretching? And... Can you show me (or explain) how to do this? (I'm not sure I understand the nitty gritty of Ack phases and repeated start signals?)
Also (and I’m not sure if I’m on the right track here), if one can bit bang the I2C pins would I still need to install pull-up resistors?
Is there anything else I can try (perhaps it's a repeated start issue--- I haven't tried to find a solution for that yet)?

I realise I could just re-program things for serial, but I’m saving those pins for a UART GPS :mrgreen:
Thanks in advance !

LeoWhite
Posts: 131
Joined: Mon Apr 08, 2013 9:20 am
Contact: Website

Re: I2C bit banging question/request

Tue Dec 22, 2015 8:24 am

Hiya,

I had similar issues with controlling my T'Rex controller via I2C on the Raspberry Pi, with the Arduino seemingly locking up in the I2C handler code. I tried various things to work around it but, at the time, the best I managed was to enable the hardware watchdog on the Arduino so it would reset after 1/4 second of no activity (Note: I had to update the bootloader on the T'Rex controller first, as the pre-installed one didn't have the watchdog properly enabled).

On a later project I was using a different Arduino and Motor Driver combination and ran into a similar issue with I2C and decided to look at alternatives. The one I settled on was the pigpio daemon/library which supports bit banging of I2C on any of the GPIO pins (http://abyz.co.uk/rpi/pigpio/python.html#bb_i2c_open). Since changing over to that I've not noticed any I2C lockups on my Arduino that has a hardware I2C interface, although my other Arduino still locks up from time to time...

There's some python examples on the pigpio website and my own C++ code can be found at https://github.com/LeoWhite/OptimusPi/b ... rs/I2C.cpp

Leo

FumblePi
Posts: 6
Joined: Mon Dec 21, 2015 6:06 pm
Location: In a Galaxy Far far away ...

Re: I2C bit banging question/request

Thu Dec 24, 2015 1:08 pm

LeoWhite wrote: I had similar issues with controlling my T'Rex controller via I2C on the Raspberry Pi, with the Arduino seemingly locking up in the I2C handler code. I tried various things to work around it but, at the time, the best I managed was to enable the hardware watchdog on the Arduino so it would reset after 1/4 second of no activity (Note: I had to update the bootloader on the T'Rex controller first, as the pre-installed one didn't have the watchdog properly enabled).
Leo
Thanks for your reply! I'm glad to know that I'm not the only person who has had this problem... I'm much luckier to have some support though!

pigpio is an excellent solution to the problem! Thanks to your code (after deciphering it--- don't know much C++, but I’m getting there), and to some help from Joan the developer of pigpio, I have the T'rex up and running.

I'm putting this up for anyone who wants it, or just for people who are curious...
My current setup is as follows:
- Simple T'rex arduino sketch (unfortunately not the original--- although I'll be working on that now)
- pigpio on the RPi2.
I've defined specific routines for forward, reverse, right, left, pivoting and stop on the T'rex. The RPi sends 3 bytes (vs the 27 in the original sketch) to work. The first is a startbyte (error checking) with a value of 15 (0x0F), followed by the command byte (forward, reverse, right, left, stop, etc), followed by the speed of the motor. I'm looking into making it much more elegant, but this is what I can do/ am learning to do, at the moment.

T'rex Sketch: (parts of which are from the original T'rex sample code by Oddbot)

Code: Select all

#include <Wire.h>                                      // interrupt based I2C library
#include <Servo.h>                                     // library to drive up to 12 servos using timer1
//#include <EEPROM.h>                                    // library to access EEPROM memory
//#include "IOpins.h"  
#define left_encoder_pin     6  //  D6 - left  motor encoder input - optional
#define right_encoder_pin    5  //  D5 - right motor encoder input - optional

#define lm_brk_pin     4  //  D4 - left  motor brk        control    pin    HIGH = brk 
#define lm_dir_pin     2  //  D2 - left  motor direction    control    pin    HIGH = Forward   Low = Reverse
#define lm_pwm_pin     3  //  D3 - left  motor pulse width  modulation pin    0 - 255          Speed and brk 
#define lm_cur_pin     6  //  A6 - left  motor current      monitor    pin    0 - 1023         -20A to +20A   

#define rm_brk_pin     9  //  D9 - right motor brk        control    pin    HIGH = brk 
#define rm_dir_pin    10  // D10 - right motor direction    control    pin    HIGH = Forward   Low = Reverse
#define rm_pwm_pin    11  // D11 - right motor pulse width  modulation pin    0 - 255          Speed and brk 
#define rm_cur_pin     7  //  A7 - right motor current      monitor    pin    0 - 1023         -20A to +20A   

#define voltspin     3  //  A3 - battery voltage          1V = 33.57        30V = 1007

#define axisxpin     0  //  A0 - accelerometer X-axis
#define axisypin     1  //  A1 - accelerometer Y-axis
#define axiszpin     2  //  A2 - accelerometer Z-axis


byte slave_address = 7;
//command bytes
byte CMD_FWD = 0x01;
byte CMD_REV = 0x02;
byte CMD_RT = 0x03;
byte CMD_LT = 0x04;
byte CMD_Piv_RT = 0x05;
byte CMD_Piv_LT = 0x06;
byte CMD_STOP = 0x07;
byte CMD_OFF = 0x08;
int LSpeed = 0;
int RSpeed = 0;
int Speed =0 ;
byte startbyte = 0x0F; // start with byte 15
byte errorflag; //dont really know what this is
byte recvflag;
byte cmd;
void setup() 
{
  Serial.begin(9600);
  Serial.print("hello");
  TCCR2B = TCCR2B & B11111000 | B00000110;
  // Start I2C Bus as Slave
  Wire.begin(slave_address);
  Wire.onReceive(receiveEvent);

  //motor setup
  pinMode(lm_pwm_pin,OUTPUT);                            // configure left  motor PWM       pin for output
  pinMode(lm_dir_pin,OUTPUT);                            // configure left  motor direction pin for output
  pinMode(lm_brk_pin,OUTPUT);                            // configure left  motor brk     pin for output

  pinMode(rm_pwm_pin,OUTPUT);                            // configure right motor PWM       pin for output
  pinMode(rm_dir_pin,OUTPUT);                            // configure right motor direction pin for output
  pinMode(rm_brk_pin,OUTPUT);                            // configure right motor brk     pin for output


}  
void loop() 
{
  //Serial.print (Wire.read());
  //delay (1000);
}
void receiveEvent(int howMany) 
{
  byte b;
  int i;
  //Serial.print(b);
  do
  {
    b=Wire.read();
    Serial.println(b);
    if(b!=startbyte)errorflag = errorflag | 1;
  } while (errorflag>0 &&Wire.available()>0);
  
  if(errorflag>0)
  {
    Serial.print("error ");
    Serial.println(errorflag);
    return;
  }
  
  b=Wire.read();
  if (b>0 && b<9)
  {
    cmd=b;
    Serial.println(b);
  }
  else
  {
    errorflag =errorflag |2;
  }
  i=Wire.read();//*256+Wire.read();
  if(i>-1 && i<256)
  {
    Speed=i;
    Serial.println(i);
  }
  else 
  {
    errorflag =errorflag |3;
  }
  Serial.println(cmd,Speed);
  //delay(50000);
  if (cmd == CMD_FWD){
    digitalWrite(lm_brk_pin,LOW);                     // if left brk>0 then engage electronic braking for left motor
    digitalWrite(lm_dir_pin,1);                     // if left speed>0 then left motor direction is forward else reverse
    analogWrite (lm_pwm_pin,Speed);                  // set left PWM to absolute value of left speed - if brk is engaged then PWM controls braking
    //if(lmbrk>0 && lmspeed==0) lmenc=0;                  // if left brk is enabled and left speed=0 then reset left encoder counter

    digitalWrite(rm_brk_pin,LOW);                     // if right brk>0 then engage electronic braking for right motor
    digitalWrite(rm_dir_pin,HIGH);                     // if right speed>0 then right motor direction is forward else reverse
    analogWrite (rm_pwm_pin,Speed);                  // set right PWM to absolute value of right speed - if brk is engaged then PWM controls braking
    //if(rmbrk>0 && rmspeed==0) rmenc=0;                  // if right brk is enabled and right speed=0 then reset right encoder counter 
    //Serial.println('Forward 100');  
  }
  if (cmd == CMD_REV){
    digitalWrite(lm_brk_pin,LOW);                     // if left brk>0 then engage electronic braking for left motor
    digitalWrite(lm_dir_pin,LOW);                     // if left speed>0 then left motor direction is forward else reverse
    analogWrite (lm_pwm_pin,Speed);                  // set left PWM to absolute value of left speed - if brk is engaged then PWM controls braking
    //if(lmbrk>0 && lmspeed==0) lmenc=0;                  // if left brk is enabled and left speed=0 then reset left encoder counter

    digitalWrite(rm_brk_pin,LOW);                     // if right brk>0 then engage electronic braking for right motor
    digitalWrite(rm_dir_pin,LOW);                     // if right speed>0 then right motor direction is forward else reverse
    analogWrite (rm_pwm_pin,Speed);                  // set right PWM to absolute value of right speed - if brk is engaged then PWM controls braking
    //if(rmbrk>0 && rmspeed==0) rmenc=0;                  // if right brk is enabled and right speed=0 then reset right encoder counter 
    //Serial.println('Reverse 100');  
  }
  if (cmd == CMD_LT){ //RIGHT
    digitalWrite(lm_brk_pin,HIGH);                     // if left brk>0 then engage electronic braking for left motor
    digitalWrite(lm_dir_pin,HIGH);                     // if left speed>0 then left motor direction is forward else reverse
    analogWrite (lm_pwm_pin,0);                  // set left PWM to absolute value of left speed - if brk is engaged then PWM controls braking
    //if(lmbrk>0 && lmspeed==0) lmenc=0;                  // if left brk is enabled and left speed=0 then reset left encoder counter

    digitalWrite(rm_brk_pin,LOW);                     // if right brk>0 then engage electronic braking for right motor
    digitalWrite(rm_dir_pin,HIGH);                     // if right speed>0 then right motor direction is forward else reverse
    analogWrite (rm_pwm_pin,Speed);                  // set right PWM to absolute value of right speed - if brk is engaged then PWM controls braking
    //if(rmbrk>0 && rmspeed==0) rmenc=0;                  // if right brk is enabled and right speed=0 then reset right encoder counter 
    //Serial.println('Left 100');  
  }
  if (cmd == CMD_RT){ //LEFT
    digitalWrite(lm_brk_pin,LOW);                     // if left brk>0 then engage electronic braking for left motor
    digitalWrite(lm_dir_pin,HIGH);                     // if left speed>0 then left motor direction is forward else reverse
    analogWrite (lm_pwm_pin,Speed);                  // set left PWM to absolute value of left speed - if brk is engaged then PWM controls braking
    //if(lmbrk>0 && lmspeed==0) lmenc=0;                  // if left brk is enabled and left speed=0 then reset left encoder counter

    digitalWrite(rm_brk_pin,HIGH);                     // if right brk>0 then engage electronic braking for right motor
    digitalWrite(rm_dir_pin,HIGH);                     // if right speed>0 then right motor direction is forward else reverse
    analogWrite (rm_pwm_pin,0);                  // set right PWM to absolute value of right speed - if brk is engaged then PWM controls braking
    //if(rmbrk>0 && rmspeed==0) rmenc=0;                  // if right brk is enabled and right speed=0 then reset right encoder counter 
    //Serial.println('Right 100');  
  }
  if (cmd == CMD_Piv_RT){
    digitalWrite(lm_brk_pin,LOW);                     // if left brk>0 then engage electronic braking for left motor
    digitalWrite(lm_dir_pin,HIGH);                     // if left speed>0 then left motor direction is forward else reverse
    analogWrite (lm_pwm_pin,Speed);                  // set left PWM to absolute value of left speed - if brk is engaged then PWM controls braking
    //if(lmbrk>0 && lmspeed==0) lmenc=0;                  // if left brk is enabled and left speed=0 then reset left encoder counter

    digitalWrite(rm_brk_pin,LOW);                     // if right brk>0 then engage electronic braking for right motor
    digitalWrite(rm_dir_pin,LOW);                     // if right speed>0 then right motor direction is forward else reverse
    analogWrite (rm_pwm_pin,Speed);                  // set right PWM to absolute value of right speed - if brk is engaged then PWM controls braking
    //if(rmbrk>0 && rmspeed==0) rmenc=0;                  // if right brk is enabled and right speed=0 then reset right encoder counter 
    //Serial.println('Pivot_right 100');  
  }
  if (cmd == CMD_Piv_LT){
    digitalWrite(lm_brk_pin,LOW);                     // if left brk>0 then engage electronic braking for left motor
    digitalWrite(lm_dir_pin,LOW);                     // if left speed>0 then left motor direction is forward else reverse
    analogWrite (lm_pwm_pin,Speed);                  // set left PWM to absolute value of left speed - if brk is engaged then PWM controls braking
    //if(lmbrk>0 && lmspeed==0) lmenc=0;                  // if left brk is enabled and left speed=0 then reset left encoder counter

    digitalWrite(rm_brk_pin,LOW);                     // if right brk>0 then engage electronic braking for right motor
    digitalWrite(rm_dir_pin,HIGH);                     // if right speed>0 then right motor direction is forward else reverse
    analogWrite (rm_pwm_pin,Speed);                  // set right PWM to absolute value of right speed - if brk is engaged then PWM controls braking
    //if(rmbrk>0 && rmspeed==0) rmenc=0;                  // if right brk is enabled and right speed=0 then reset right encoder counter 
    //Serial.println('Pivot_left 100');  
  }
  if (cmd == CMD_STOP){
    digitalWrite(lm_brk_pin,HIGH);                     // if left brk>0 then engage electronic braking for left motor
    digitalWrite(lm_dir_pin,LOW);                     // if left speed>0 then left motor direction is forward else reverse
    analogWrite (lm_pwm_pin,0);                  // set left PWM to absolute value of left speed - if brk is engaged then PWM controls braking
    //if(lmbrk>0 && lmspeed==0) lmenc=0;                  // if left brk is enabled and left speed=0 then reset left encoder counter

    digitalWrite(rm_brk_pin,HIGH);                     // if right brk>0 then engage electronic braking for right motor
    digitalWrite(rm_dir_pin,LOW);                     // if right speed>0 then right motor direction is forward else reverse
    analogWrite (rm_pwm_pin,0);                  // set right PWM to absolute value of right speed - if brk is engaged then PWM controls braking
    //if(rmbrk>0 && rmspeed==0) rmenc=0;                  // if right brk is enabled and right speed=0 then reset right encoder counter 
    //Serial.print("aaahhahahahaaaa --- Stopping");
  }
}
On the Raspberry side I've used python and pygame with a PS3-like gamepad controller to control the robot. It's not complete yet, but you get the idea of what I want to do.

Code: Select all

#!/usr/bin/env python
# Tea_rex.py   Because we like tea not coffee
# run by doing
# sudo python Tea_rex.py

## Send commands to T'rex Via bit-banged I2C pins on Raspberry pi 2

## Imports
import sys
import smbus
import time
import pygame
#from pygame.locals import *
#bus = smbus.SMBus(1)    #Not needed since we are bit banging the I2C Pins using pigpio
import pigpio

# I2C address of Arduino Slave
address = 0x07

#T'rex Bytes defined in Arduino sketch (on T'rex)
CMD_FWD = 0x01;	#Forward
CMD_REV = 0x02;	#Reverse
CMD_RT = 0x03;	#Right Motors Forward
CMD_LT = 0x04;	#Left Motors Forward
CMD_Piv_RT = 0x05;	#Pivot Left (rt FWD lt REV)
CMD_Piv_LT = 0x06;	#Pivot Right (lt FWD rt REV)
CMD_STOP = 0x07;	#Stop everything (Brake essentially)
CMD_OFF = 0x08;	#Off ... not defined yet

# define pins for bit banging on Pi
# pigpio ALWAYS uses Broadcom GPIO numbering

SDA=2   #this is pin number 3
SCL=3   #this is pin number 5

pi = pigpio.pi() # Connect to Pi.

''' Definitions for bitbanging subroutines follow here
	they are called in the while loop: e.g. forward(speed)
	the speed is determined by the value given by the potentiometer
	on the gamepad, and multiplied by 255 to give a speed that is
	passed to the T'rex
	'''
def forward(speed):
	
	(count, data) = pi.bb_i2c_zip(SDA, [4, 0x07, 2, 7, 3, 0x0F, CMD_FWD, speed, 3, 0])
	print(count, data)
def reverse(speed):
	(count, data) = pi.bb_i2c_zip(SDA, [4, 0x07, 2, 7, 3, 0x0F, CMD_REV, speed, 3, 0])
	print(count, data)
def right(speed):
	(count, data) = pi.bb_i2c_zip(SDA, [4, 0x07, 2, 7, 3, 0x0F, CMD_RT, speed, 3, 0])
def left(speed):
	(count, data) = pi.bb_i2c_zip(SDA, [4, 0x07, 2, 7, 3, 0x0F, CMD_LT, speed, 3, 0])
def pivot_right(speed):
	(count, data) = pi.bb_i2c_zip(SDA, [4, 0x07, 2, 7, 3, 0x0F, CMD_Piv_RT, speed, 3, 0])
def pivot_left(speed):
	(count, data) = pi.bb_i2c_zip(SDA, [4, 0x07, 2, 7, 3, 0x0F, CMD_Piv_LT, speed, 3, 0])
def stop():
	(count, data) = pi.bb_i2c_zip(SDA, [4, 0x07, 2, 7, 3, 0x0F, CMD_STOP, 0x00, 3, 0])




#main program
try:
	if not pi.connected:
		exit(0)
	#pigpiod must be running or this won't even load! 
	
	pi.bb_i2c_open(SDA, SCL, baud=100000) # Prepare to bit bang.
	
	#initialize pygame
	pygame.init()
	j = pygame.joystick.Joystick(0)
	j.init()
	print 'Initialized Joystick : %s' % j.get_name()
	print 'number of buttons : %s' % j.get_numbuttons()
	## Thank you Pygame##


	Keep_playing = True
	while (Keep_playing):
		for event in pygame.event.get():
			if event.type == pygame.QUIT:
				print ("Received event 'Quit', exiting.")
				keepPlaying = False
			elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
				print ("Escape key pressed, exiting.")
				keepPlaying = False
			elif event.type == pygame.KEYDOWN:
				print ("Keydown,", event.key)
			elif event.type == pygame.KEYUP:
				print ("Keyup,", event.key)

	#####################################################---Joystick-Axis---###################################################3###3

			elif event.type == pygame.JOYAXISMOTION:
				if event.dict['axis'] == 0 and event.dict['value'] > 0:
					my_percent = event.dict['value']
					speed = abs (int(my_percent *255))
					right(speed)
					print (speed)
					print ('Left-joy 0 --- 0 Right', event.dict)
				elif event.dict['axis'] == 0 and event.dict['value'] < 0:
					my_percent = event.dict['value']
					speed = abs (int(my_percent *255))
					print (speed)
					left(speed)
					print ('Left-joy 0 --- 0 Left', event.dict)
				elif event.dict['axis'] == 1 and event.dict['value'] > 0:
					my_percent = event.dict['value']
					speed = abs (int(my_percent *255))
					print (speed)
					reverse(speed)
					print ('Left-joy 1 --- 1 Down', event.dict)
				elif event.dict['axis'] == 1 and event.dict['value'] < 0:
					my_percent = event.dict['value']
					speed = abs (int(my_percent *255))
					forward(speed)
					print (speed)
					print ('Left-joy 1 --- 1 UP', event.dict)
				elif event.dict['axis'] == 2 and event.dict['value'] > 0:
				# This joy stick will be used to control a servo
					my_percent = event.dict['value']
					speed = abs (int(my_percent *255))
					print (speed)
					print ('Right-joy 2 --- 2 Right', event.dict)
				elif event.dict['axis'] == 2 and event.dict['value'] < 0:
					my_percent = event.dict['value']
					speed = abs (int(my_percent *255))
					print (speed)
					print ('Right-joy 2 --- 2 Left', event.dict)
				elif event.dict['axis'] == 3 and event.dict['value'] > 0:
					my_percent = event.dict['value']
					speed = abs (int(my_percent *255))
					print (speed)
					print ('Right-joy 3 --- 3 Down', event.dict)
				elif event.dict['axis'] == 3 and event.dict['value'] < 0:
					my_percent = event.dict['value']
					speed = abs (int(my_percent *255))
					print (speed)
					print ('Right-joy 3 --- 3 UP', event.dict)
					#print "Joystick '",j.get_name(),"' axis",event.axis,"motion."

	####################################################---Joystick-Buttons-Down (Press-Down)---###########################################

			elif event.type == pygame.JOYBUTTONDOWN :
	#			print "Joystick '",j.get_name(),"' button",event.button,"down.", event.dict
				if event.button == 0:
					forward(100) 
					print ('Button 0 pressed		   ',event.dict)
				if event.button == 1:
					pivot_right(100)
					print ('Button 1 pressed')
				if event.button == 2:
					print ('Button 2 pressed')
					reverse(100)
				if event.button == 3:
					print ('Button 3 pressed')
					pivot_left(100)
					#pivot_left(st)		####----------------->Pivot left
				if event.button == 4:
					stop()
					#estop(st)####----------------------------------------------------> EMERGENCY BRAKE
					print ('Button 4 pressed   ---- EMERGENCY BRAKE!!!!')
					#estop()
					#time.sleep(0.5)####----------------------------------------->wait 0.3 seconds
				if event.button == 5:
					print ('Button 5 pressed ---- Taking a Picture!!! ')
					#os.system('raspistill --nopreview -t 1 -q 10 -o Rover.jpg -th 0:0:0 &')#####------> Take a Picture!  Button 5 
				if event.button == 6:
					print ('Button 6 pressed')
				if event.button == 7:
					print ('Button 7 pressed')
				if event.button == 8:
					print ('Button 8 pressed	 ---------  Recording a Video ')
					#os.system('raspivid -o myvid.h264 -w 720 -h 405 -t 60000') #####  --------------> Record a Video (1min)   Button 8
				if event.button == 9:
					print ('Button 9 pressed')
					#os.system('sudo reboot')		####---------------------------------> Restart Pi Button 9
				if event.button == 10:
					print ('Button 10 pressed')
				if event.button == 11:
					print ('Button 11 pressed .... Exiting')


	############################################---Joystick-Buttons-UP (Button Release)---###############################################

			elif event.type == pygame.JOYBUTTONUP:
				#print "Joystick '",j.get_name(),"' button",event.button,"down.", event.dict
				if event.button == 0:
				
					print ('Button 0 released  ---- BRAKE Lights ON') 
					stop()
				elif event.button == 1:
					stop()					##STOP--- BRAKE
					print ('Button 1 released')
				elif event.button == 2:
					stop()					##STOP--- BRAKE
					print ('Button 2 released')
				elif event.button == 3:
					print ('Button 3 released')
					stop()#command								##STOP--- BRAKE
				elif event.button == 4:
					print ('Button 4 released')
					stop()#command								##STOP--- BRAKE
				elif event.button == 5:
					print ('Button 5 released')
					stop()#command								##STOP--- BRAKE
				elif event.button == 6:
					print ('Button 6 released')
					stop()#command								##STOP--- BRAKE
				elif event.button == 7:
					print ('Button 7 released')
					stop()#command								##STOP--- BRAKE
				elif event.button == 8:
					print ('Button 8 released')
				elif event.button == 9:
					print ('Button 9 released')
					#command
				elif event.button == 10:
					print ('Button 10 released')
					#command
				elif event.button == 11:
					print ('Button 11 pressed .... Exiting')		#command
					stop()
					pygame.quit()
					sys.exit()
	#################################################--- Hat Buttons (D-Pad controllers) ---#############################################

			elif event.type == pygame.JOYHATMOTION:
	#			print "Joystick '",j.get_name(),"' hat",event.hat," moved.",event.dict
				if event.dict['hat'] == 0 and event.dict['value'] == (0, 0):
					#estop(st)					###STOP when hat released
					print ('D-Pad release !!!  ---- Stopping/BRAKE  ', event.dict)
				elif event.dict['hat'] == 0 and event.dict['value'] == (0, -1):
					print ('D-Pad Down ---- Gear DOWN! ', event.dict)
					#Possibly change motors pwm setting later
				elif event.dict['hat'] == 0 and event.dict['value'] == (0, 1):
					print ('D-Pad Up ---- Gear UP! ', event.dict)
					#gear_up_FWD(st)
				elif event.dict['hat'] == 0 and event.dict['value'] == (-1, 0):
					print ('D-Pad Left  ----  Turn Left ', event.dict)
					#turn_left(st)					####--------------> Turn Left
				elif event.dict['hat'] == 0 and event.dict['value'] == (1, 0):
					print ('D-Pad Right  ----  Turn Right ', event.dict)
					#turn_right(st)					####--------------> Turn Right
except:
	stop()
	pi.bb_i2c_close(SDA) # Stop bit banging I2C.

	pi.stop() # Disconnect from Pi.
I haven't quite figured out how to sent the correct number of bytes to the original T'rex sketch, or even how to read the sensors on it (yet). Any bits of code are much appreciated... But for now it's time for me to do some work.

Merry Christmas!

LeoWhite
Posts: 131
Joined: Mon Apr 08, 2013 9:20 am
Contact: Website

Re: I2C bit banging question/request

Fri Dec 25, 2015 8:02 pm

Hiya,
FumblePi wrote:
LeoWhite wrote: I had similar issues with controlling my T'Rex controller via I2C on the Raspberry Pi, with the Arduino seemingly locking up in the I2C handler code. I tried various things to work around it but, at the time, the best I managed was to enable the hardware watchdog on the Arduino so it would reset after 1/4 second of no activity (Note: I had to update the bootloader on the T'Rex controller first, as the pre-installed one didn't have the watchdog properly enabled).
Leo
Thanks for your reply! I'm glad to know that I'm not the only person who has had this problem... I'm much luckier to have some support though!

pigpio is an excellent solution to the problem! Thanks to your code (after deciphering it--- don't know much C++, but I’m getting there), and to some help from Joan the developer of pigpio, I have the T'rex up and running.
I had to decipher some Python code to come up with that C++ code :D
FumblePi wrote: I'm putting this up for anyone who wants it, or just for people who are curious...
My current setup is as follows:
- Simple T'rex arduino sketch (unfortunately not the original--- although I'll be working on that now)
- pigpio on the RPi2.
I've defined specific routines for forward, reverse, right, left, pivoting and stop on the T'rex. The RPi sends 3 bytes (vs the 27 in the original sketch) to work. The first is a startbyte (error checking) with a value of 15 (0x0F), followed by the command byte (forward, reverse, right, left, stop, etc), followed by the speed of the motor. I'm looking into making it much more elegant, but this is what I can do/ am learning to do, at the moment.
I had an error checking byte in my original code, although since switching to pigpio on my latest project I've removed it for now. Keeps the code a little simpler!
FumblePi wrote:
I haven't quite figured out how to sent the correct number of bytes to the original T'rex sketch, or even how to read the sensors on it (yet). Any bits of code are much appreciated... But for now it's time for me to do some work.
The code I ran on my T'Rex controller for PiWars 2014 can be found at https://github.com/LeoWhite/BiggerTrak/ ... BiggerTrak This was controlled using a python script (https://github.com/LeoWhite/BiggerTrak/ ... gerTrak.py) and was before I had switched over to pigpio, but maybe it will be of use!

Leo

Return to “Interfacing (DSI, CSI, I2C, etc.)”