Friday, February 20, 2015

Using the Arduino IDE to run 1Sheeld sketches on a pcDuino

In a previous post, I provided a modified library and samples for using the 1Sheeld on a pcDuino (2 or 3) using the pcDuino Arduino-ish libraries (c_environment).   If, however, you want to compile sketches for the 1Sheeld on the pcDunio using the Arduino IDE, there are some additional things you need to do.   I've also taken pains to make sure that the changes I talk about here are integrated into the Arduino Libraries in such a way that you can still use them if you are connecting an Arduino to the pcDuino and using the 1Sheeld on the Arduino ... so, the exact same libraries can be used for Ardunio/1Sheeld sketches or pcDuino/1Sheeld sketches.

 <<< TERMIO ISSUES >>>  
 You may want to add this somewhere to your start-up configuration ... 
 or create an easily accessible script somewhere.  
 stty -onlcr -icrnl -F /dev/ttyS1   
 If you don't, using some of the Shields won't work as-expected ... 
 and if you ever need to you can always do this to reset to default: 

 stty onlcr icrnl -F /dev/ttyS1  
 If you really want to make a code change ... you will have to modify
 the Serial.cpp module to add this somewhere in the begin function 
 (I tested with it right before the tcsetattr() call ...   
  Opt.c_iflag &= ~(ICRNL);   
  Opt.c_oflag &= ~(ONLCR);   
 There are a couple of shields that are affected if these changes aren't
 in place (Terminal and Internet Shields are known to have problems).  

First, let me say that the changes to the OneSheeld library are pretty much identical to the changes made to compile with the c_environment (arduino-ish libraries).   Second, from what I can tell at this point, you won't have to change the sample sketches at all (no additional forward declarations required) and third, originally, you had to make changes to the Serial.cpp file to get this all to work ... but now, it's all OneSheeld library changes.  Every thing that needs to be changed or added is highlighted in Red below.

Note:  New v1.5 requirements ... After copying the Arduino Library and Samples to you pcDuino, delete the file from the library directory (OneSheeld) or the Arduino IDE included with pcDuinos will throw an error (and not load).

So, let's get started with the code changes.


OneSheeld Library changes ... 

1. OneSheeld.h - should be found in /home/ubnutu/Arduino/libraries/OneSheeld 

Add the following to just below the #define OneSheeld_h line ...

 #ifdef PCDUINO_IDE  
 #define PCDUINO 1  
 #define ARDUINO_LINUX 1  

The reason for these additional lines is to change things a bit for pcDuino when the OneSheeld libraries compile.   The ARDUINO_LINUX #define is already used by the OneSheeld libraries and defining it fixes a couple things so the libraries will compile for us.   The PCDUINO #define is new and we're going to make a couple changes to the OneSheeld libraries so things will compile properly.  The #ifdef PCDUINO_IDE check indicates that we only want to do the other #defines if we are compiling for the PCDUINO.  If we have an Arduino connected, we won't #define PCDUINO or ARDUINO_LINUX at all.

Also add the following  above the #include "Stream.h" line.

 #ifdef PCDUINO  
   typedef unsigned char byte;  

2. OneSheeld.cpp - again, should be found in /home/ubnutu/Arduino/libraries/OneSheeld 
put the following code around the #include "HardwareSerial.h" line ...

 #ifdef PCDUINO  
 #include "Serial.h"  
 #include "HardwareSerial.h"  

also, add the extra checks for the PCDUINO definition in the begin method and where the OneSheeld object gets instantiated ... 

 void OneSheeldClass::begin(long baudRate)  
  #if defined(__AVR_ATmega32U4__) || (defined(ARDUINO_LINUX) && !defined(PCDUINO))  

 #if defined(__AVR_ATmega32U4__) || (defined(ARDUINO_LINUX) && !defined(PCDUINO))  
 OneSheeldClass OneSheeld(Serial1);  
 void serialEvent1()  
 OneSheeldClass OneSheeld(Serial);  
 void serialEvent()  
 #ifdef PCDUINO  

Finally, we need to add an additional parameter to the pulseIn calls in the analogRead method ...

 static unsigned long analogReadTimeout = 1000000L;  
 unsigned char OneSheeldClass::analogRead(int pin)  
   double period=(double)pulseIn(pin,HIGH,analogReadTimeout)+(double)pulseIn(pin,LOW,analogReadTimeout);  
   double duty=(double)pulseIn(pin,HIGH,analogReadTimeout);  
   double fraction=duty/period;  
   unsigned char pwm_out=(unsigned char)(ceil)(fraction*255);  
   return pwm_out;  

That is all that you should have to do to use the Arduino IDE when compiling OneSheeld sketches with the 1Sheeld sitting on the pcDuino.   

Also, if you already had the pcDuino OneSheeld library changes in place, make sure you revert back to the original Serial.cpp module ... remove the comment tags that commented out the serialEvent() and serialEventRun() functions and delete the newer serialEventRun() function.

  #define serialEvent_implemented   
  void serialEvent()   
  void serialEventRun(void)   
  #ifdef serialEvent_implemented   
  void serialEventRun(void)   

Please remember to select the pcDuino as the Board in the Arduino IDE.   Make sure you pick the right Serial Port (if you don't have an Arduino connected, it should be the only port available).  

Also, set the power switch to 3.3V (since that's what pcDuino wants) ... and you can just leave the UART/SWITCH set to UART ... since you will be just compiling to the files system and running an executable.  That switch can just stay where it is.

These are the same changes that I made for the c_environment version. The big difference is the Arduino IDE version doesn't need the forward declarations added to the samples (which would probably have worked if needed).


02-24-2015 - removed requirement to modify the pcDuino version of Arduino.h ... now the only original pcDuino library change is to Serial.cpp (and it's the exact same change that is needed for the Arduino-ish [c_environment] version). 

03-05-2015 - no changes are required to the pcDuino library now (none, zero, zilch, zip) ... all necessary changes are part of the OneSheeld library ... and the changes made to the OneSheeld Library are done in a way (wrapped in #ifdefs)  that you can still use the library for either pcDuino compiles or Arduino compiles without any additional changes.

03-09-2015 - Updated for compatibility with Arduino v1.4 library and samples.

05-06-2015 - New requirement for v1.5 library noted above.

Monday, February 16, 2015

All post's source code downloads now point to Github

As of 02-16-2015 all source code (libraries, sample, sketches, etc) download links in the Arduino CodeDog blog posts that I've created have been changed and now point to public Github repositories.

All future source code downloads will point to Github repositories as well.

Friday, February 6, 2015

1Sheeld's GamePad and a Gameduino and you are Good-To-Go

After converting the Arduino Libraries to C# for Netduino I needed a little play time.  So, I decided to dig out my Gameduino and see what I could come up with.  It didn't take long to think "hmmm, 1Sheeld's GamePad may just work for the Frogger demo that the Gameduino folks have provided" ... and a small change to the Frogger Sketch (adding 1Sheeld Gamepad support) and voila, Frogger on an Arduino with 1Sheeld GamePad support...very, very cool!

Here's the entire Controller class using the OneSheeld library GamePad support, #include the OneSheeld.h at the top of the Frogger sketch and you will be crossing the street with a frog in tow in no time.

 class Controller {  
   void begin() {  
    prev = 0;  
   byte read() {  
    byte r = 0;  
    if (GamePad.isDownPressed())  
     r |= CONTROL_DOWN;  
    if (GamePad.isUpPressed())  
     r |= CONTROL_UP;  
    if (GamePad.isLeftPressed())  
     r |= CONTROL_LEFT;  
    if (GamePad.isRightPressed())  
     r |= CONTROL_RIGHT;  
    byte edge = r & ~prev;  
    prev = r;  
    return edge;  
   byte prev;  

Put the 1Sheeld on an Arduino UNO r3 (or similar), put the Gameduino on the 1Sheeld.

For Manic Miner (updated):

Well, what I thought would work doesn't (the code I placed here earlier just doesn't seem to want to work).   What I have found is that it seems like it's best to just define pins on the 1Sheeld GamePad (rather than using the GamePad class) and then tweak the Manic Miner code like below:

 /* Setup 1Sheeld Gamepad Buttons to point to some pins... I used analog pins, but it probably doesn't matter. */  
 #define PIN_L A2  
 #define PIN_R A3  
 #define PIN_J A5  
 /* This was already in the code, but I just copied and pasted everything that needs some changes ... nothing here though */  
 #define CONTROL_LEFT 1  
 #define CONTROL_RIGHT 2  
 #define CONTROL_JUMP 4  
 /* Don't do any of the digitalWrite's in the setup_control() function ... I just commented them out... all we have to do is setup the pin modes for input. */  
 static byte setup_control()  
  pinMode(PIN_L, INPUT);  
  digitalWrite(PIN_L, HIGH);   
  pinMode(PIN_R, INPUT);  
  digitalWrite(PIN_R, HIGH);  
  pinMode(PIN_J, INPUT);  
  digitalWrite(PIN_J, HIGH);  
 /* Finally get rid of the ! in front of the digital read calls, we want the character to jump or move when we press the button(s) ... note, this was fine for the hardware joysticks, but for the 1Sheeld Game Pad, we need to do things a bit different! */  
 static byte control()  
  byte r = 0;  
  if (!digitalRead(PIN_J))  
   r |= CONTROL_JUMP;  
  if (!digitalRead(PIN_L))  
   r |= CONTROL_LEFT;  
  if (!digitalRead(PIN_R))  
   r |= CONTROL_RIGHT;  
  return r;  

One of the benefits of doing it this way is you don't have to load the OneSheeld libraries at all, so the code stays small enough to run on an UNO too!!!

Frogger could have been done similarly.


02-15-2015 - Updated changes for Manic Miner to work.