View Full Version : CRIO ARDUINO INTERFACE
Robototes2412
17-05-2010, 11:00
Hey, i got bored and wrote this:
package com.shadowh511.mayor.utils;
import edu.wpi.first.wpilibj.SerialPort;
/**
*
* @author Team 2412
*/
public class Arduino {
/*
* Hopefully, i will be able to have an arduino be hooked up to the robot
* and communicate with the serial port. I can use this to do many things,
* such as maintain a LCD screen and display data on it to help the electrical
* and mechanical teams figure out what went wrong.
*
* In all realism, it will most likely just be a fun cool thing for me to
* play with :D
*/
private SerialPort serial;
public Arduino() {
try {
serial = new SerialPort(115200);
this.serial.disableTermination();
this.serial.print("h");
System.out.println("Arduino Starting, waiting 0.5 seconds to get data");
String e = this.getData();
edu.wpi.first.wpilibj.Timer.delay(0.125);
if(e.equals("h")) {
System.out.println("Arduino communications locked in");
}
}
catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
}
}
public String getData() {
try {
return this.serial.readString();
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return null;
}
}
public boolean sendData(byte[] buffer) throws Exception {
try {
int count = buffer.length;
this.serial.write(buffer, count);
return true;
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return false;
}
}
public boolean printf(String data) {
try {
this.serial.print(data);
return true;
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return false;
}
}
public String requestData() {
try {
this.serial.print("r");
return this.serial.readString();
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return null;
}
}
public int requestData(String request) {
try {
this.serial.print(request);
return NumberUtils.stringToInt(this.getData());
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return 0;
}
}
}
Hook up an arduino to the serial port and have it run a program that toggles pin number 13. Bind a button to sending h and a button to sending l. have fun pushing the buttons, you just made a polyglot robot! :D
Jeremy Germita
26-05-2010, 03:35
I like the whole idea of this!
I had an idea like this in march, but it was far more complex.
Can I play around with it? I'd like to possibly help improve on this.
Robototes2412
26-05-2010, 19:07
all my code is gpl'd so go at it. It doesn't reliably work ATM, so can you help me fix it please?
Jeremy Germita
27-05-2010, 16:54
I'll be glad to help. I can do some testing in starting in July.
Maybe we can have a working version by the 2011 Build Season!
What seems to be the problem?
Just a thought... Does your team use CAN? If yes, I think that this could interfere with that. Maybe have an alternate mode using the ADC and the DIO. Using 2 12 bit channels of the ADC, we can have a simple protocol to convert the returned int(or is it double?) into a char.
Robototes2412
28-05-2010, 10:41
This goes directly through the serial port on the Robot.
I am working on a bit of Arduino code that will let me see if the serial port is being used for anything.
I think the following will work:
void setup() {
Serial.begin(/*Maximum Serial Rate*/);
}
void loop() {
Serial.println(Serial.read());
}
Assuming you have your arduino hooked up to your laptop and the robot's serial port hooked up to the arduino with the TX to RX and the ground, or Pins 2 and 5.
Jeremy Germita
28-05-2010, 18:27
That sounds like a good idea. Ill post some code of the alternate comms when I get the chance.
Jeremy Germita
28-05-2010, 22:20
here is a rough idea of the constructor
public void robotInit() {
Arduino arduinoEx = new Arduino(CommsMode commsMode,int inChannel, int outChannel);
Arduino arduinoAn = new Arduino(CommsMode.kAnalog, 1); //Analog, channel 1
Arduino arduinoDig = new Arduino(CommsMode.kDigital, 7, 8); //Digital, Channels 7 and 8
Arduino arduinoSer = new Arduino(CommsMode.kSerial, baudRate); //Serial, baudRate
Arduino arduinoI2C = new Arduino(CommsMode.kI2C, 1);
}
ControlMode - Analog(with a digital Pot), Digital(with the DIO pins of the crio and arduino), Serial, I2C, etc
int inChannel - Digital-the recieving pin
Analog-The input pin
Serial-Not Needed
I2C-The address on the bus
int OutChannel-Digital only- the sending pin
long BaudRate - Serial Only, self explanatory
I'll write something up in the library to show you how the constructors would work
Jeremy Germita
30-05-2010, 04:18
About the unreliability, could you please explain this?
Is it timing? Maybe we can do something like a signal set HIGH to indicate
an incomming serial transmission and vice versa for the cRio.
I'm not sure about the levels of the Serial port on the cRio, but maybe the
levels are different. A solution to this could be using the MAX233 level
converter IC.
How is the 'duino powered? Maybe your USB port has some problem. How
about make a power adaptor(PD-Board to 3.5mm Barrel Jack). And maybe a
filter cap to smooth out any signal problems caused by rapidly dropping
voltage due to a motor starting up or similar. The regulator on the arduino
can handle the 12 volts as long you aren't powering a current-hog(servos,
lot's of led's, etc). If you are using the LCD as you said, maybe that is
drawing abnormally large amounts of current(just a thought)
Also, can we move this to PM's or email? Perferably email. PM me if yes:D
michael714
07-06-2010, 00:22
Don't move to PM's. Other people want to add an Arduino interface to the cRio. Like me. Thanks!
Don't move to PM's. Other people want to add an Arduino interface to the cRio. Like me. Thanks!
Ditto.
-Tanner
Robototes2412
07-06-2010, 11:01
Well, our pm convo isn't alive anymore.
As far as the interface goes, I need people to help me test it (no changes since release 0)
can someone also post a copy of the serial output of the cRIO booting? (I have no serial port :( )
Jeremy Germita
07-06-2010, 12:43
I'd like to get some javadoc stuff done before i get my new Arduino, so...
-----
Can someone bring up the rule(s) about custom circuitry?
I recall a section on this. I know that as long as it is commercially available, code and circuitry are legal, but what about the arduino perhipherals(protoshields)?
What if I want to make a custom shield that logs data on a microSD card and indicate various things with bright LED's(hypothetical)
PS The shield mentioned above exists here (http://www.sparkfun.com/commerce/product_info.php?products_id=9802)
PPS This shield has a prototyping area, ruling on that please!
PPPS There are other (simpler) alternatives to the hypothetical question(cRio Flash, DIO, etc), I realize this
-----
What about the arduino code? what if you wrote a Serial/I2C read-/write-er and LCD interface? Does this apply in the "Available to All Teams" rule?(Forgive me, I don't remember rule numbers, just the rules.)
-----
What if I use a custom variant of the arduino board? Like a perfboard barebones? I'm pretty sure the basic schematic of the barebones is available on the site...
-----
Not doubting this project, I just want to document this with any rules users may run into.
Can someone bring up the rule(s) about custom circuitry?
I recall a section on this. I know that as long as it is commercially available, code and circuitry are legal, but what about the arduino perhipherals(protoshields)?
What if I want to make a custom shield that logs data on a microSD card and indicate various things with bright LED's(hypothetical)
PS The shield mentioned above exists here (http://www.sparkfun.com/commerce/product_info.php?products_id=9802)
PPS This shield has a prototyping area, ruling on that please!
I'm no expert on rules, but looking through them you've got <R03>, <R45>F/G, <R50>, and <R68>. That's all I got for doing a quick search for "custom". I can't read them right now in depth to give a good answer, but I'll leave that to someone else.
Phototyping is always good for LEDs and whatever else you could want.
What about the arduino code? what if you wrote a Serial/I2C read-/write-er and LCD interface? Does this apply in the "Available to All Teams" rule?(Forgive me, I don't remember rule numbers, just the rules.)
The building things in non-season rules? If I remember correctly, it's fine as long as its shared with other teams. 'Course again I'm no expert on the rules.
Note to self: I should work on this, I've got a arduino that needs a project.
We should set up a github to share code and manage it as it is being worked on.
-Tanner
Jeremy Germita
09-06-2010, 03:45
Tanner, Thanks for the quick rulings.
Also, I think that it is a great idea to set up a github!
Jeremy Germita
09-06-2010, 10:10
Robototes2412,
You have a google account right? You can set up a Google Code account to host this project.
Robototes2412,
You have a google account right? You can set up a Google Code account to host this project.
I can set up one as I'm already using GitHub to work on several other FRC projects, I just didn't want to step on anyone's toes.
I think using Git is better (http://whygitisbetterthanx.com/) for version control, but that's just me.
Cheers
-Tanner
Robototes2412
09-06-2010, 19:44
Personally, I like bazaar.
Jeremy Germita
09-06-2010, 21:42
I think using Git is better (http://whygitisbetterthanx.com/) for version control, but that's just me.
I didn't really look at the advantages, I was just too lazy to create an account on another website :P. I was also thinking of hosting other projects of mine on Google Code.
But that's just me.
Back on topic:
Project Hosting? Where? Any improvements?
Ya'll are welcome to choose whichever system/site as I'm just a contributor at this point, but I probably will not be able to contribute to code if it is hosted by Google (job prevents me from getting a Google account which is what you need afaik). I can do GitHub (hence my suggestion), but it's a bit different and slightly complicated, so it could be a bit tough to learn. There's a lot of good resources out there about it though.
-Tanner
Jeremy Germita
10-06-2010, 08:30
I have no problem learning github, if Robotes2414 chooses it. I'm just happy to contribute
Jeremy Germita
14-06-2010, 08:02
I have written several changes to the code while on vacation in the Philippines,
I wish I could post it, but I have no WiFi:( and the internet cafe I am currently typing this from has a no USB drive policy:(
Changes:
Digital comms
I2C comms
I have also started writing a library for the arduino. If you already have written one, I can stop.
I will post them when i return stateside on the 23rd.
Robototes2412
14-06-2010, 10:55
I haven't worked on it, ive been too busy with finals, as kanye said, go nuts go ape $h1+
Jeremy Germita
23-06-2010, 09:49
Here's what I have done over the last few weeks:
I commented some parts. I highlighted the comment with the list of changes.
I have created the methods, but nothing in them yet...
package com.shadowh511.mayor.utils;
import edu.wpi.first.wpilibj.SerialPort;
import edu.wpi.first.wpilibj.DigitalInput;
import edu.wpi.first.wpilibj.DigitalOutput;
import edu.wpi.first.wpilibj.I2C;
import edu.wpi.first.wpilibj.DigitalModule;
/**
* Arduino
* @author Team 2412
*/
public class Arduino {
/*
* Hopefully, i will be able to have an arduino be hooked up to the robot
* and communicate with the serial port. I can use this to do many things,
* such as maintain a LCD screen and display data on it to help the electrical
* and mechanical teams figure out what went wrong.
*
* In all realism, it will most likely just be a fun cool thing for me to
* play with :D
*/
/*
**Changes by jeremypg399:************************************** ***********
* -I2C Constructor
* -Digital Constructor
* -Added methods:
* boolean isIdle() //Returns true if no data is being sent/recieved
* boolean isValid() //Returns True if comms work
* boolean digitalRead(int pin) //Same as in the Arduino language
* void setLed(boolean state) //Sets the onboard LED
* void digitalWrite(int pin, boolean state) //Same as in the Arduino Language
* void analogWrite(int pin) //Same as in the Arduino Language
* int analogRead(int pin) //Same as in the Arduino Language
* -Created variables to accomodate above changes
*
* Everything I have added pin-wise was considering All Arduino boards with
* analog pins 0-5(I2C on pins 4, 5), Digital pins 0-13(Serial on 0 and 1, led on 13)
* Some tweaking will be necessary in order to use the Arduino Mega
*/
private SerialPort serial;
private DigitalInput digIn;
private DigitalOutput digOut;
private I2C I2C;
public int m_I2CAddress;
public int m_digInChannel;
public int m_digOutChannel;
private CommsMode m_commsMode;
private final int TRANS_PULSE_LENGTH = 30;
private byte[] buffer =
{0, 0, 0, 0, 0, 0, 0};
private boolean[] pinConfigs = //An array storing the configurations of pins
{false, false, false, false, //Default is output
false, false, false, false, //True-Input, False-Output
false, false, false }; //Digital Pins 2-12(Pin 0 Reserverd
//for serial, pin 13 reserved for LED)
private boolean[] analogPinConfigs = //An array for the config's of analog pins
{true, true, true, //True-AnalogIn DigitalIn, False-kI2C DigitalOut
true, true, true }; //Pins 4 and 5 will be configured as outputs
//if using kI2C
/**
* Constructor
* @param comms the CommsMode
* @param in If kSerial, Baud Rate, if kI2C, Address on bus
*/
public Arduino(CommsMode comms, int in) {
if(comms.equals(CommsMode.kSerial)) {
try {
if(in > 100) {
System.out.println("Invalid Baud Rate--Are you sure you " +
"want to use serial?");
} else {
serial = new SerialPort(in);
this.serial.disableTermination();
this.serial.print("h");
System.out.println("Arduino Starting, waiting 0.5 seconds to get data");
String e = this.getData();
edu.wpi.first.wpilibj.Timer.delay(0.125);
m_commsMode = CommsMode.kSerial;
if(e.equals("h")) {
System.out.println("Arduino communications locked in");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else if(comms.equals(CommsMode.kI2C)) {
I2C = new I2C(DigitalModule.getInstance
(DigitalModule.getDefaultDigitalModule()), in);
this.m_I2CAddress = in;
this.I2C.write(in, 0);
if(this.I2C.read(m_I2CAddress, 1, buffer)) {
System.out.println("Error. No reply from Arduino. ");
} else {
System.out.println("Arduino Communications locked in");
}
} else if(comms.equals(null)) {
System.out.println("Invalid Communications Mode");
}
}
/**
* Constructor.
* @param comms The CommsMode, kDigital
* @param inChannel The Digital input channel to use
* @param outChannel The digital output channel to use
*/
public Arduino(CommsMode comms, int inChannel, int outChannel) {
if(comms.equals(CommsMode.kDigital)) {
digIn = new DigitalInput(inChannel);
digOut = new DigitalOutput(outChannel);
m_commsMode = comms;
} else {
System.out.println("Invalid Communications Mode");
}
}
/**
* Constructor.
* Defaults to Serial at 115200 Baud
*/
public Arduino() {
m_commsMode = CommsMode.kSerial;
try {
serial = new SerialPort(115200);
this.serial.disableTermination();
this.serial.print("h");
System.out.println("Arduino Starting, waiting 0.5 seconds to get data");
String e = this.getData();
edu.wpi.first.wpilibj.Timer.delay(0.125);
if(e.equals("h")) {
System.out.println("Arduino communications locked in");
}
}
catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
}
}
public static class CommsMode {
public final int value;
static final int kDigital_val = 1;
static final int kAnalog_val = 2;
static final int kI2C_val = 3;
static final int kSerial_val = 4;
public static final CommsMode kDigital = new CommsMode(kDigital_val);
public static final CommsMode kAnalog = new CommsMode(kAnalog_val);
public static final CommsMode kI2C = new CommsMode(kI2C_val);
public static final CommsMode kSerial = new CommsMode(kSerial_val);
private CommsMode(int value) {
this.value = value;
}
}
public String getData() {
try {
return this.serial.readString();
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return null;
}
}
public boolean sendData(byte[] buffer) throws Exception {
try {
int count = buffer.length;
this.serial.write(buffer, count);
return true;
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return false;
}
}
public boolean printf(String data) {
try {
this.serial.print(data);
return true;
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return false;
}
}
public String requestData() {
try {
this.serial.print("r");
return this.serial.readString();
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return null;
}
}
public int requestData(String request) {
try {
this.serial.print(request);
return stringToInt(this.getData());
} catch (Exception e) {
System.out.println("something went wrong, " + e.getMessage());
return 0;
}
}
/**
* Used to check if the Arduino is not communicating at that given instance.
* @return True if the Arduino is not communicating, else false.
*/
public boolean isIdle() {
if(m_commsMode.equals(CommsMode.kDigital)) {
return false;
} else if(m_commsMode.equals(CommsMode.kSerial)) {
return false;
} else if(m_commsMode.equals(CommsMode.kI2C)) {
return false;
} else {
return false;
}
}
/**
* Sends data and waits for a response. Used to check if the arduino is
* still on and/or connected
* @return True if the Arduino responds, else false
*/
public boolean isValid() {
if(m_commsMode.equals(CommsMode.kDigital)) {
return false;
} else if(m_commsMode.equals(CommsMode.kSerial)) {
return false;
} else if(m_commsMode.equals(CommsMode.kI2C)) {
return false;
} else {
return false;
}
}
/**
* Toggles the onboard LED conneected to pin 13
* @param state
*/
public void setLed(boolean state) {
if(m_commsMode.equals(CommsMode.kDigital)) {
} else if(m_commsMode.equals(CommsMode.kSerial)) {
} else if(m_commsMode.equals(CommsMode.kI2C)) {
}
}
/**
* Toggles a digital pin designated as an output
* Does nothing if the pin has been configured as an input
* @param pin the digital pin to toggle
* @param state The state to write it to
*/
public void digitalWrite(int pin, boolean state) {
if(m_commsMode.equals(CommsMode.kDigital)) {
} else if(m_commsMode.equals(CommsMode.kSerial)) {
} else if(m_commsMode.equals(CommsMode.kI2C)) {
}
}
/**
* Gets the state of the digital input.
* Does nothing if the pin has been configured as an input
* @param pin The pin to query
* @return A boolean dependent on the digital input
*/
public boolean digitalRead(int pin) {
if(m_commsMode.equals(CommsMode.kDigital)) {
} else if(m_commsMode.equals(CommsMode.kSerial)) {
} else if(m_commsMode.equals(CommsMode.kI2C)) {
}
}
/**
* Writes a PWM wave to a pin. Must be a PWM pin.
* If a non PWM pin is given, or if the pin has been configured as an input,
* nothing will happen
* @param pin
*/
public void analogWrite(int pin) {
if(m_commsMode.equals(CommsMode.kDigital)) {
} else if(m_commsMode.equals(CommsMode.kSerial)) {
} else if(m_commsMode.equals(CommsMode.kI2C)) {
}
}
/**
* Gets the analog input on pins 0-5.
* @param pin The analog pin to query
* @return The int read by the Arduino (0-1023)
*/
public int analogRead(int pin) {
if(m_commsMode.equals(CommsMode.kDigital)) {
} else if(m_commsMode.equals(CommsMode.kSerial)) {
} else if(m_commsMode.equals(CommsMode.kI2C)) {
}
}
private int stringToInt(String data) {
}
}
Personally, I think the methods for digitalRead, digitalWrite, analogRead, and analogWrite violate a rule. I believe there is the rule that restricts all digital and analog signals to originate from or go to the cRIO or digital sidecar. But they are there if they are safe.
Apologies for not being specific, but I don't remember numbers :P
Robototes2412
23-06-2010, 12:34
it says you can't use any custom circuits to do command signals, but as far as, say, an LCD goes were good.
Jeremy Germita
03-07-2010, 00:57
Can someone point me to the pinout of the I2C Port on the Digital Sidecar?
I'm making some cables, but I have no access to a robot until school starts.
I believe it is a 4 or 5 pin Male header on the Digital Sidecar.
Much appreciated,
Jeremy
Mark McLeod
03-07-2010, 08:25
You can see the I2C header here (http://www.chiefdelphi.com/forums/attachment.php?attachmentid=8455&d=1264980108)
5v (+)
SCL
SDA
Gnd (-)
vBulletin® v3.6.4, Copyright ©2000-2017, Jelsoft Enterprises Ltd.