0

i need to send live joystick data from Pygame to my Arduino so arduino can then communicate over serial to my dsm2 module(for RC planes). i wrote code and got it working but had to have a delay this was not suitable for RC plane flight and is not live like i wanted could anyone please help and write an example or fix my code

raspberry pi:

import pygame
import time
import smbus
import time
import os

bus = smbus.SMBus(1)

address = 0x07
def writeNumber(v1,v2,v3,v4,v5,v6):
        bus.write_i2c_block_data(address,v1,[v2,v3,v4,v5,v6])
        return -1
def valmap(value, istart, istop, ostart, ostop):
  return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))

pygame.init()

# Set the width and height of the screen [width,height]
size = [1, 1]
screen = pygame.display.set_mode(size)

pygame.display.set_caption("My Game")


# Used to manage how fast the screen updates
clock = pygame.time.Clock()

# Initialize the joysticks
pygame.joystick.init()
# -------- Main Program Loop -----------
while True:
    time.sleep(0.2)
    # EVENT PROCESSING STEP
    for event in pygame.event.get():

        # Possible joystick actions: JOYAXISMOTION JOYBALLMOTION JOYBUTTONDOWN JOYBUTTONUP JOYHATMOTION
        if event.type == pygame.JOYBUTTONDOWN:
            print("Joystick button pressed.")
        if event.type == pygame.JOYBUTTONUP:
            print("Joystick button released.")

    joystick_count = pygame.joystick.get_count() 
    # For each joystick:
    for i in range(joystick_count):
        joystick = pygame.joystick.Joystick(i)
        joystick.init()

        # Usually axis run in pairs, up/down for one, and left/right for
        # the other.
        axes = joystick.get_numaxes()
        for i in range( axes ):
            axis = valmap(joystick.get_axis( i ), -1, 1, 0, 200)
            print("Axis {} value: {:>6.3f}".format(i, axis) )

        writeNumber(int(valmap(joystick.get_axis(3), -1, 1, 0, 200)),int(valmap(joystick.get_axis(0), -1, 1, 0, 200)),int(valmap(joystick.get_axis(1), -1, 1, 0, 200)),int(valmap(joystick.get_axis(2), -1, 1, 0, 200)),200,200)


    # Limit to 20 frames per second
    clock.tick(16)

# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit ()

Arduino removed i2c code:

#include "Arduino.h"
#include "dsm2_tx.h"

#define BIND_SWITCH  2
#define BIND_LED     3
#define ERROR_LED    5
DSM2_tx tx(6);
int ch0;
int ch1;
int ch2;
int ch3;
int ch4;
int ch5;
int angle = 0;
int newAngle = 0;
const int MaxChars = 4;
char strValue[MaxChars+1];
int index = 0;
/*
 * This is the callback for the bind process--it controls the UI during the bind process
 * Bind completed:  state = 0
 * Bind in progress:  state = 1
 * Bind error:  state = 2
 */
void bind_cb( int state, byte model_id ) {
  if( state == 1 ) {
    digitalWrite(BIND_LED, HIGH);
  }
  else {
    digitalWrite(BIND_LED, LOW);
  }
  if( state == 2 ) {
    digitalWrite(ERROR_LED, HIGH);
  }
}

#define MAX_VAL 200
int reverse(int valuetr, int MIN, int MAX) {
  int reversed_int;
  reversed_int =  (MAX - valuetr) + MIN;
  return reversed_int;
}


void setup() {
  pinMode(BIND_SWITCH, INPUT);
  pinMode(BIND_LED, OUTPUT);
  pinMode(ERROR_LED, OUTPUT);

  tx.begin();

  if( digitalRead(BIND_SWITCH) == HIGH ) {
    digitalWrite(ERROR_LED, HIGH);
    tx.bind(bind_cb);
  }
}



void loop() {
  tx.set_channel(0, ch0, MAX_VAL);
  tx.set_channel(1, ch1, MAX_VAL);
  tx.set_channel(2, ch2, MAX_VAL);
  tx.set_channel(3, ch3, MAX_VAL);
  tx.set_channel(4, ch4, MAX_VAL);
  tx.set_channel(5, ch5, MAX_VAL);
  tx.send_frame();
}
  • i got it to work but it is more reliable if i use my new solution which is to just use the raspberry pi – ethan Johnston Nov 11 '16 at 13:28
1

Check this first: there is a bug in the i2c hardware of the Raspberry Pi (see here). This bug makes communicating with an Arduino unreliable at the default speed... It is wise to test your setup with a much reduced i2c baudrate first. For me, it worked by adding

dtparam=i2c_arm_baudrate=10000

to the /boot/config.txt file.

  • I was struggling for a few hours at something that should have been easy to resolve. I haven't tested different rates, but this definitely got me on my way. Works on my Uno units, as well as my Trinket Pro units seamlessly. – stevieb Jun 22 '17 at 23:09
0

Your Python has

while True:
    time.sleep(0.2)

That means there are at most 5 positional updates per second.

If you change 0.2 to 0.02 you will get up to 50 updates per second which will make your RC device more responsive.

  • the arduino cuts out if i send to many bites at once – ethan Johnston Oct 29 '16 at 12:31
  • That is a failing of the Arduino. You will have to experiment to find the minimum safe delay at the Pi end. – joan Oct 29 '16 at 12:36
0

Ethan,

Can you post the code that didn't work? I'm like to understand what you meant by "cutting out"

I've found that the occasional I2C I/O error is fairly common when communicating between an Rpi and Arduino. You should ensure that your code has a method of handling what happens when a dropped byte or a missed read occurs. For example, parse the I2C byte read before sending the value to a servo so you don't drive the servo to an erroneous position on bus error. The I2C bus by default clocks at 100 KHz per this reference http://playground.arduino.cc/Main/WireLibraryDetailedReference an occasional "pass" in the code when a read error occurs should't be too noticeable in your system at 100 KHz.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.