1/ Arduino DUE

 

1.1/ Keyboard : (attached to "FS Hat" PC)

 

Arduino DUE has to behave as a keyboard, so I will use the <keyboard.h> lib. But all the keys are not included in this lib, so an extension is needed to add extra keys:

 

keyboard_ext.h  ______________________________________________________________

/*

  Keyboard_ext.h

 

  keyboard extension adapted from

  https://github.com/rampadc/arduino-thinkpadkb-usb/blob/master/MicroThinkPadAdapter/MicroThinkPadAdapter.ino

*/

 

//================================================================================

//  extended Keyboard

 

#define KEY_PAUSE           0xD0

#define KEY_PRINT_SCREEN    0xCE

#define KEY_SCROLL_LOCK     0xCF

#define KEYPAD_NUMLOCK      0xDB

#define KEYPAD_0            0xEA

#define KEYPAD_1            0xE1

#define KEYPAD_2            0xE2

#define KEYPAD_3            0xE3

#define KEYPAD_4            0xE4

#define KEYPAD_5            0xE5

#define KEYPAD_6            0xE6

#define KEYPAD_7            0xE7

#define KEYPAD_8            0xE8

#define KEYPAD_9            0xE9

#define KEYPAD_SLASH        0xDC

#define KEYPAD_ASTERISK     0xDD

#define KEYPAD_MINUS        0xDE

#define KEYPAD_PLUS         0xDF

#define KEYPAD_ENTER        0xE0

#define KEYPAD_PERIOD       0xEB

__________________________________________________________________________

 

1.2/ Digital inputs: (44 inputs)

 

As explained in the previous part, I exploit interrupts for each of them,  attachInterrupt(pin#, _function, RISING);

Some of the inputs are not yet used, but foreseen for "future extension"...

In the interrupt  _function, I just set a flag (flag |= specialBit) to be read in the main loop. Once tested in the main loop (if flag & specialBit), a special action/function is processed.

I use 3 kind of flags; either a key has to be written to the keyboad (kbCharW), or a char/chain has to be sent to serial link (sndStrFlag), or a key has to be first pressed or released (kbCharPR).

To avoid using many loops to test the bits of the 3 flags (3 x 3 loops), I'd gathered them in common loops (as long as the number of bits to test are equal)

 

 

1.3/ Analog inputs: (Steering wheel, accel pedal, accel hand, brakes pedal)

 

A0 to A3 values are scaled with my own map function (see why below in analog outputs part). I had preferred tuning my inputs in the range 0.1V to 3.2V (see hardware) to avoid negative/overvoltage on the arduino.

curVal = myMap(analogRead(analogInputPin), 124, 3971);

In the 12 bits resolution range [0, 4095] for [0V, 3.3V], [124, 3971] corresponds to [0.1V, 3.2V].

However, even if the potentiometers powered with max +/- 15 V (see hardware), some analog inputs max value (accelerations) were around 2.4 V. That's why I had to adjust the "3971" values for them.

The scaled values are sent directly to the analog outputs.

 

 

1.4/ Analog outputs: (Steering wheel, accel forward, accel backward, brakes)

 

As already mentioned, I had preferred using PWM as I needed 4 analog outputs in the full range [0, 3.3V] voltage.

However, this feature needs some code changes in the arduino lib, to set 12 bits resolution and high PWM frequency (even if I filter @80Hz, to be far from Shannon critical frequencies).

So in C:\Users\{user}\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.11\variants\arduino_due_x\variant.h

values to set (in bold):

/*

* PWM

*/

#define PWM_INTERFACE    PWM

#define PWM_INTERFACE_ID ID_PWM

#define PWM_FREQUENCY 6000

#define PWM_MAX_DUTY_CYCLE 4095

#define PWM_MIN_DUTY_CYCLE 0

#define PWM_RESOLUTION 12

 

During the testings, I spent a lot of time to find an error that occured on my analog outputs. The system crashed each time I was at an extremum value of my potentiometers.

I had to use the serial monitor to find the error message duty <= pPwm->PWM_CH_NUM[ul_channel].PWM_CPRD" failed: file "../source/pwmc.c", line 272, function: PWMC_SetDutyCycle

I finally found on internet (thanks google), that it came from the arduino map function (it sometimes returns negative values, which is incompatible with PWM function)! See here.

 

So I wrote my own map function:

unsigned int myMap(float val, float minin, float maxin) {

  return min((unsigned int) max(0., (val - minin) * (float)maxV12 / (maxin - minin)), maxV12);

}

 

 

1.5/ Serial link:

 

Set to 115200 bps, it receives and sends data.To gain in reactivity I use just a few bytes (some characters).

A first loop retreives all the incoming characters (while (Serial.available())) while in the other scanning loops the bits are tested to know which chain to send to the serial link.

All the data sent to the serial link will be forwarded to TCP/IP with "PS_Hat" PC. So, to optimise the TCP/IP bandwidth (even if it's in a 1Gb/s local net, yes limited to 100Mb/s due the the raspberry pis), I set a flag to limit the sendings.

okToSend = ((unsigned long)(t1 - t0) >= dt); // cast to avoid to manage roll-over

 

BTW,  here how to handle millis roll over ...

 

 

inputsDUE.c  _______________________________________________________________

/*

  Program Arduino DUE

  Manage tractor inputs for Farming Simulator

  Damien Hallez, nov 2017

*/

 

#include <Keyboard.h>

#include "Keyboard_ext.h"

 

// ======================================================================================

//                  DECLARATIONS

// ======================================================================================

// ----- ex IA1

// const short pin_JSC_Left   =  52 ;    // ---- Joystick Cabin Left

// const short pin_JSC_Right  =  68 ;    // ---- Joystick Cabin Right

// const short pin_JSC_Frwd   =  50 ;    // ---- Joystick Cabin Forward

// const short pin_JSC_Bkwd   =  69 ;    // ---- Joystick Cabin Backward

// const short pin_FSp_PB     =  64 ;    // ---- Fix speed button

const short pin_Neutral    =  47 ;    // ---- Neutral for/back ward

const short pin_Horn       =  42 ;    // ---- Horn      => '0_'

const short pin_Beacon     =  16 ;    // ---- Beacon    => 'HOME' + beacon= to Rpi_Disp & Rpi_Out

// ----- ex IB1

// const short pin_JSC_H4     =  65 ;    // ---- Joystick Cabin H4

// const short pin_JSC_H3     =  62 ;    // ---- Joystick Cabin H3

// const short pin_JSC_Pl     =  66 ;    // ---- Joystick Cabin +

// const short pin_JSC_Ms     =  63 ;    // ---- Joystick Cabin -

// const short pin_JSC_PB     =  64 ;    // ---- Joystick Cabin Push Button

const short pin_SeqLev_PB  = 48 ;    // ---- Sequential lever Push Button   => 'O'

// const short pin_SeqLev_SP  =  53 ;    // ---- Sequential lever speed +

// const short pin_SeqLev_SM  =  46 ;    // ---- Sequential lever speed -

// ----- ex IA2

const short pin_Li_FrDown  = 14 ;    // ---- Lights Front Low => 'F/3F' + LghtFrDown/LghtReDown to Rpi_Disp & Rpi_Out

const short pin_Li_FrUp    = 17 ;    // ---- Lights Front Up  => 'KP5'  + LghtFrUp to Rpi_Disp & Rpi_Out

const short pin_Li_ReDown  = 15 ;    // ---- Lights Rear Low  => 'F/3F' + LghtFrDown/LghtReDown to Rpi_Disp & Rpi_Out

const short pin_Li_ReUp    = 18 ;    // ---- Lights Rear Up   => 'KP6'  + LghtReUp to Rpi_Disp & Rpi_Out

// const short pin_PB1       =  19 ;    // ---- Push Button 1

// const short pin_PB2       =  20 ;    // ---- Push Button 2

// const short pin_PB3       =  26 ;    // ---- Push Button 3

// const short pin_PB5       =  28 ;    // ---- Push Button 5

// ----- ex IB2

// const short pin_Frwd_Up   =  53 ;    // ---- sequential forward speed Up

// const short pin_Frwd_Down =  46 ;    // ---- sequential forward speed Down

// const short pin_Bkwd_Up   =  53 ;    // ---- sequential backward speed Up

// const short pin_Bkwd_Down =  46 ;    // ---- sequential backward speed Down

const short pin_Warning      = 37 ;    // ---- Warning button   => 'KP2' + Warning=to Rpi_Disp & Rpi_Out

const short pin_BP4_N        = 21 ;    // ----- N on lights board => 'B'

const short pin_RightBlinker = 49 ;    // ----- Right Blinker   => 'KP3'

const short pin_LeftBlinker  = 44 ;    // ----- Left Blinker      => 'KP1'

// ----- ex IA3

// const short pin_SV1       =  36 ;    // ---- SV1

const short pin_A         = 38 ;    // ---- A

const short pin_UTurn     = 40 ;    // ---- U-turn        => 'G'

const short pin_LG_Up     = 29 ;    // ---- Lift Gear Up    => 'V'

const short pin_LG_Down   = 33 ;    // ---- Lift Gear Down    => 'V'

const short pin_PosN_1    = 31 ;    // ---- Position N      => 'B'

// ----- ex IB3

const short pin_HydrauLeftLeverFrwd  = 41 ; //        => 'X'

const short pin_HydrauLeftLeverBkwd  = 51 ; //        => 'X'

const short pin_HydrauRightLeverFrwd = 43 ; //        => 'I'

const short pin_HydrauRightLeverBkwd = 39 ; //        => 'I'

const short pin_GreenButtonLeftJS    = 27 ; //        => 'C'

const short pin_RedButtonLeftJS      = 30 ; //        => 'BS'

const short pin_GreenButtonRightJS   = 22 ; //        => 'PgUp'

const short pin_RedButtonRightJS     = 24 ; //        => 'PgDwn'

// ----- ex on Rpi

const short pin_FrwdInfo       = 25 ; //

const short pin_BkwdInfo       = 32 ; //

const short pin_FrwdBkwdToggle = 67 ; //

// ----- spares

// const short pinSpare1 = 34

// const short pinSpare2 = 23

// const short pinSpare3 = 45

// const short pinSpare4 = 35

 

// ----- Toggle buttons:

volatile boolean hornOn     = false;

volatile boolean beaconOn   = false;

volatile boolean warningOn   = false;

volatile boolean Li_fr_down = false;

volatile boolean Li_re_down = false;

volatile boolean Li_fr_up   = false;

volatile boolean Li_re_up   = false;

volatile boolean Lg_up      = false;

volatile boolean leftBlinkerOn  = false;

volatile boolean rightBlinkerOn = false;

volatile boolean zoomInOn = false;

volatile boolean zoomOutOn = false;

volatile boolean cameraOn = false;

volatile short Direction = 0;

 

// ----- ADC

const short in_steeringW = A0;

const short in_acc_pedal = A1;

const short in_acc_hand  = A2;

const short in_brakes    = A3;

int curStwVal    = 0;

int prevStwVal   = 0;

int curStwAngle  = 0;

int prevStwAngle = 0;

int curAccel     = 0;

int accelPedal   = 0;

int accelHand    = 0;

int prevAccel    = 0;

int curAccel2    = 0;

int prevAccel2   = 0;

int curBrksVal   = 0;

int prevBrksVal   = 0;

boolean brakesOn = false;

const int maxV12  = 4095;

 

// ----- DAC - real PWM set @6kHz

const short out_steeringW = 7;

const short out_forward   = 6;

const short out_bckward   = 5;

const short out_brakes    = 4;

 

// ----- Serial -> pins 18 & 19

char rcvString[10] ;

int nrcv = 0;

char sndString[15] ;

const short nStrAcc0         =  0;

const short nStrReRedLght    =  1;

const short nStrBeacon       =  2;

const short nStrLghtFrDown   =  3;

const short nStrLghtReDown   =  4;

const short nStrRightBlinker =  5;

const short nStrLeftBlinker  =  6;

const short nStrWarning      =  7;

const short nStrLghtFrUp     =  8;

const short nStrLghtReUp     =  9;

const short nStrToSend       = 10;

char strToSend[nStrToSend][15];

unsigned int sndStrFlag = 0;

const short bitAcc0         = 1 << nStrAcc0;

const short bitReRedLght    = 1 << nStrReRedLght;

const short bitBeacon       = 1 << nStrBeacon;

const short bitLghtFrDown   = 1 << nStrLghtFrDown;

const short bitLghtReDown   = 1 << nStrLghtReDown;

const short bitRightBlinker = 1 << nStrRightBlinker;

const short bitLeftBlinker  = 1 << nStrLeftBlinker;

const short bitWarning      = 1 << nStrWarning;

const short bitLghtFrUp     = 1 << nStrLghtFrUp;

const short bitLghtReUp     = 1 << nStrLghtReUp;

volatile boolean sendOk = false;

boolean oldSendOk = false;

volatile boolean intOk = false;

 

// ----- keyboard chars to write

char kbWlist[] = {  KEY_BACKSPACE, KEY_HOME, 'A', 'B', 'C', 'F', 'G', 'I', 'V', 'X', 'O', \

                    225, 226, 227, 229, 230, 0

                 };

volatile int kbCharW = 0;

const int bitKeyBS   = 1 <<  0;

const int bitKeyHome = 1 <<  1;

const int bitKeyA    = 1 <<  2;

const int bitKeyB    = 1 <<  3;

const int bitKeyC    = 1 <<  4;

const int bitKeyF    = 1 <<  5;

const int bitKeyG    = 1 <<  6;

const int bitKeyI    = 1 <<  7;

const int bitKeyV    = 1 <<  8;

const int bitKeyX    = 1 <<  9;

const int bitKeyO    = 1 << 10;

const int bitKP1     = 1 << 11;

const int bitKP2     = 1 << 12;

const int bitKP3     = 1 << 13;

const int bitKP5     = 1 << 14;

const int bitKP6     = 1 << 15;

const short nCharWList    = 16;

 

// ----- keyboard chars to press/release

char kbPRlist[] = { KEY_PAGE_UP, KEY_PAGE_DOWN, '0', 0  };

volatile short kbCharPR = 0;

const short bitKeyPgUpPress    = 1 << 0;

const short bitKeyPgUpRelease  = 1 << 1;

const short bitKeyPgDwnPress   = 1 << 2;

const short bitKeyPgDwnRelease = 1 << 3;

const short bitKey0Press       = 1 << 4;

const short bitKey0Release     = 1 << 5;

const short nCharPRList             = 3; /// divided by 2 (set, released)

 

// ----- keyboard special send

volatile boolean kbCharSeqFFF   = false;

volatile boolean kbCharSeqFFF5  = false;

volatile boolean kbCharSeqFFF6  = false;

volatile boolean kbCharSeq5F5   = false;

volatile boolean kbCharSeq6F6   = false;

volatile boolean kbCharSeq56F56 = false;

 

// index

short il;

unsigned int jl, kl, ll;

char *addStr;

 

// manage the time to send data (avoid overflow)

unsigned long t0, t1;

int dt = 100; // ms to send data to serial

boolean okToSend = false;

 

// verify if not blocked ...

unsigned long tHorn0;

int dtHorn = 5000; // ms max to be maintained

boolean forceReleaseButtons = false;

int releaseCnt = 0;

 

// ======================================================================================

//                    SETUP

// ======================================================================================

void setup() {

  // -------------------------------------------- Serial (makes a reset !!)

  Serial.begin(115200);

 

  // -------------------------------------------- Strings to be sent

  // firt letter : 0 = reset com, 1 = send to Disp,  2 = send both to Disp and Outputs

  // then 3 letters, then value

  strcpy(strToSend[nStrAcc0]        , "1ACC0.00" ); // accel

  strcpy(strToSend[nStrReRedLght]   , "2RRL0" ); // ReRedLght

  strcpy(strToSend[nStrBeacon]      , "2BCN0" ); // Beacon

  strcpy(strToSend[nStrLghtFrDown]  , "2LFD0" ); // LghtFrDown

  strcpy(strToSend[nStrLghtReDown]  , "2LRD0" ); // LghtReDown

  strcpy(strToSend[nStrRightBlinker], "2RBL0" ); // RightBlinker

  strcpy(strToSend[nStrLeftBlinker] , "2LBL0" ); // LeftBlinker

  strcpy(strToSend[nStrWarning]     , "2WRN0" ); // Warning

  strcpy(strToSend[nStrLghtFrUp]    , "2LFU0" ); // LghtFrUp

  strcpy(strToSend[nStrLghtReUp]    , "2LRU0" ); // LghtReUp

 

  // -------------------------------------------- Buttons

  // ----- position N     -> 'B'

  attachInterrupt(pin_PosN_1, _posN, RISING);

  attachInterrupt(pin_BP4_N,  _posN, RISING);

  // ----- Horn         -> '0'

  attachInterrupt(pin_Horn, _hornOn, RISING);

  // ----- Beacon       -> 'HOME'

  attachInterrupt(pin_Beacon, _beacon, RISING);

  // ----- action 1       -> 'O'

  attachInterrupt(pin_SeqLev_PB, _act_o, RISING);

  // ----- lights Front low     -> KP5

  attachInterrupt(pin_Li_FrDown, _lght_fr_low, RISING);

  // ----- lights Rear low     -> KP6

  attachInterrupt(pin_Li_ReDown, _lght_re_low, RISING);

  // ----- Right Blinker    -> KP3

  attachInterrupt(pin_RightBlinker, _rightBlinkOn, RISING);

  // ----- Left Blinker   -> KP1

  attachInterrupt(pin_LeftBlinker, _leftBlinkOn, RISING);

  // ----- Warning      -> KP0

  attachInterrupt(pin_Warning, _WarningOn, RISING);

  // ----- light FR UP    -> KP5

  attachInterrupt(pin_Li_FrUp, _lght_fr_up, RISING);

  // ----- light RE UP    -> KP6

  attachInterrupt(pin_Li_ReUp, _lght_re_up, RISING);

  // ----- U-Turn       -> 'G'

  attachInterrupt(pin_UTurn, _u_turn, RISING);

  // ----- LG_Up / LG_Down  -> 'V'

  attachInterrupt(pin_LG_Up,   _lg_up, RISING);

  attachInterrupt(pin_LG_Down, _lg_down, RISING);

  // ----- HyLeftFwd      -> 'X'

  attachInterrupt(pin_HydrauLeftLeverFrwd, _hydLeftFwd, RISING);

  attachInterrupt(pin_HydrauLeftLeverBkwd, _hydLeftBwd, RISING);

  // ----- HyRightFwd     -> 'I'

  attachInterrupt(pin_HydrauRightLeverFrwd, _hydRightFwd, RISING);

  attachInterrupt(pin_HydrauRightLeverBkwd, _hydRightBwd, RISING);

  // ----- GreenButtonLeftJS  -> 'C'

  attachInterrupt(pin_GreenButtonLeftJS, _setCamera, RISING);

  // ----- RedButtonLeftJS  -> 'BACKSPACE'

  attachInterrupt(pin_RedButtonLeftJS, _hideshowpan, RISING);

  // ----- ZoomOut      -> 'PgUp'

  attachInterrupt(pin_GreenButtonRightJS, _zoomOutOn, RISING);

  // ----- ZoomIN       -> 'PgPgDwn'

  attachInterrupt(pin_RedButtonRightJS, _zoomInOn, RISING);

  // ----- Attach       -> 'A'

  attachInterrupt(pin_A, _attach, RISING);

  // ----- Directions

  attachInterrupt(pin_FrwdInfo,      _forwardOn,  RISING);

  attachInterrupt(pin_BkwdInfo,      _backwardOn, RISING);

  attachInterrupt(pin_FrwdBkwdToggle, _toggleDir, RISING);

 

  // -------------------------------------------- Analog inputs

  analogReadResolution(12);

 

  // -------------------------------------------- Analog outputs

  analogWriteResolution(12);

  analogWrite(out_forward, 0);

  analogWrite(out_bckward, 0);

 

  // ----- reset buffer

  strcpy(rcvString, "");

 

  // ----- wait for serial PC

  while (!Serial);

 

  // -------------------------------------------- keyboard

  Keyboard.begin();

 

  t0 = millis();

 

  tHorn0 = t0;

}

 

// ======================================================================================

//                    SUBROUTINES

// ======================================================================================

// ----- send strings to the serial link

void sendSerial(char *txt) {

  if ((sendOk) && (Serial.availableForWrite() > strlen(txt))) {

    Serial.println(txt); // println add '\r\n' to the string

  }

}

// ----- azerty to qwerty

char az2qw(char inch) {

  char outch = inch;

  switch (inch) {

    case 'A': outch = 'Q'; break;

    case 'Z': outch = 'W'; break;

    case 'Q': outch = 'A'; break;

    case 'W': outch = 'Z'; break;

    case 'M': outch = ':'; break;

    case 'a': outch = 'q'; break;

    case 'z': outch = 'w'; break;

    case 'q': outch = 'a'; break;

    case 'w': outch = 'z'; break;

    case 'm': outch = ';'; break;

      break;

  }

  return outch;

}

// ----- set Direction

void setDirection(short val) {

  Direction = val;

  strToSend[nStrReRedLght][4] = char(48 + (val == -1 ? 1 : 0));

  // redLights and reset speed

  sndStrFlag  |= (bitReRedLght | bitAcc0) ;

}

//  'ESC', dt, 'UP', dt, 'ENTER'

void quitFS17() {

  delay(100);

  Keyboard.write(KEY_ESC);

  delay(200);

  Keyboard.write(KEY_UP_ARROW);

  delay(100);

  Keyboard.write(KEY_RETURN);

  delay(100);

}

// 'ESC', dt, 'RIGHT', dt, 'ENTER', dt, 'ENTER', dt

void quitGame() {

  // mask the interruptions

  intOk = false;

  Keyboard.write(KEY_ESC);

  delay(200);

  Keyboard.write(KEY_RIGHT_ARROW);

  delay(100);

  Keyboard.write(KEY_RETURN);

  delay(300);

  Keyboard.write(KEY_RETURN);

  delay(100);

}

//  n -= 1 [ 'RIGHT', dt ]n , dt, 'ENTER', dt, 'ENTER'

void loadGame(short n) {

  n -= 1;

  if (n > 20) n = 20;

  for (short ii = 0; ii < n; ii++) {

    Keyboard.write(KEY_RIGHT_ARROW);

    delay(100);

  }

  Keyboard.write(KEY_RETURN);

  delay(150);

  Keyboard.write(KEY_RETURN);

  delay(100);

  sndStrFlag  |= bitAcc0;

}

// enter normal game

void simpleGame() {

  Keyboard.write(KEY_BACKSPACE);

  delay(200);

  Keyboard.write(KEY_TAB);

  delay(100);

}

// enter game with Harvest

void harvestGame() {

  Keyboard.write(KEY_BACKSPACE);

  delay(200);

  Keyboard.write(KEY_TAB);

  delay(200);

  Keyboard.write('H');

  delay(200);

  Keyboard.write(KEY_TAB);

  delay(100);

}

 

void AltTab() {

  Keyboard.press(KEY_LEFT_ALT);

  Keyboard.press(KEY_TAB);

  delay(100);

  Keyboard.releaseAll();

  delay(100);

}

 

void ShiftAltTab() {

  Keyboard.press(KEY_LEFT_SHIFT);

  Keyboard.press(KEY_LEFT_ALT);

  Keyboard.press(KEY_TAB);

  delay(100);

  Keyboard.releaseAll();

  delay(100);

}

 

// personnal map (bug in the official one)

unsigned int myMap(float val, float minin, float maxin) {

  return min((unsigned int) max(0., (val - minin) * (float)maxV12 / (maxin - minin)), maxV12);

}

// ======================================================================================

//                    MAIN LOOP

// ======================================================================================

void loop() {

  // ------------------------------------------  commands read from serial input

  while (Serial.available()) {

    char inChar = (char)Serial.read();

    rcvString[nrcv++] = inChar;

    if (inChar == '\n') {

      rcvString[strcspn(rcvString, "\r\n")] = 0;

      // enFS, qtFS, qtGm, keyA, keyE, keyH, key{letter}, kPSC, kTAB, kENT, kBKS, kESC,

      // ld{ngame:02d}, sOk0, sOk1

      //---------------------------------------------------------------------------- keys

      // ----- simple key

      if      (strncmp(rcvString, "key", 3) == 0)   Keyboard.write(az2qw(rcvString[3]));

      // ----- special key

      else if (rcvString[0] == 'k') {

        addStr = rcvString + 1 ;

        if (rcvString[1] == 'F') {

          if      (strcmp(addStr, "F01") == 0)  Keyboard.write(KEY_F1);

          else if (strcmp(addStr, "F02") == 0)  Keyboard.write(KEY_F2);

          else if (strcmp(addStr, "F03") == 0)  Keyboard.write(KEY_F3);

          else if (strcmp(addStr, "F04") == 0)  Keyboard.write(KEY_F4);

          else if (strcmp(addStr, "F05") == 0)  Keyboard.write(KEY_F5);

          else if (strcmp(addStr, "F06") == 0)  Keyboard.write(KEY_F6);

          else if (strcmp(addStr, "F07") == 0)  Keyboard.write(KEY_F7);

          else if (strcmp(addStr, "F08") == 0)  Keyboard.write(KEY_F8);

          else if (strcmp(addStr, "F09") == 0)  Keyboard.write(KEY_F9);

          else if (strcmp(addStr, "F10") == 0)  Keyboard.write(KEY_F10);

          else if (strcmp(addStr, "F11") == 0)  Keyboard.write(KEY_F11);

          else if (strcmp(addStr, "F12") == 0)  Keyboard.write(KEY_F12);

          delay(100);

        }

        else if (rcvString[1] == 'K') {

          if      (strcmp(addStr, "KP0") == 0)  Keyboard.write(KEYPAD_0);

          else if (strcmp(addStr, "KP1") == 0)  Keyboard.write(KEYPAD_1);

          else if (strcmp(addStr, "KP2") == 0)  Keyboard.write(KEYPAD_2);

          else if (strcmp(addStr, "KP3") == 0)  Keyboard.write(KEYPAD_3);

          else if (strcmp(addStr, "KP4") == 0)  Keyboard.write(KEYPAD_4);

          else if (strcmp(addStr, "KP5") == 0)  Keyboard.write(KEYPAD_5);

          else if (strcmp(addStr, "KP6") == 0)  Keyboard.write(KEYPAD_6);

          else if (strcmp(addStr, "KP7") == 0)  Keyboard.write(KEYPAD_7);

          else if (strcmp(addStr, "KP8") == 0)  Keyboard.write(KEYPAD_8);

          else if (strcmp(addStr, "KP9") == 0)  Keyboard.write(KEYPAD_9);

          else if (strcmp(addStr, "KP/") == 0)  Keyboard.write(KEYPAD_SLASH);

          else if (strcmp(addStr, "KP*") == 0)  Keyboard.write(KEYPAD_ASTERISK);

          else if (strcmp(addStr, "KP-") == 0)  Keyboard.write(KEYPAD_MINUS);

          else if (strcmp(addStr, "KP+") == 0)  Keyboard.write(KEYPAD_PLUS);

          else if (strcmp(addStr, "KPE") == 0)  Keyboard.write(KEYPAD_ENTER);

          else if (strcmp(addStr, "KP.") == 0)  Keyboard.write(KEYPAD_PERIOD);

          delay(100);

        }

        else if (rcvString[1] == 'P') {

          if      (strcmp(addStr, "PSC") == 0)  Keyboard.write(KEY_PRINT_SCREEN);

          else if (strcmp(addStr, "PGU") == 0)  Keyboard.write(KEY_PAGE_UP);

          else if (strcmp(addStr, "PGD") == 0)  Keyboard.write(KEY_PAGE_DOWN);

          else if (strcmp(addStr, "PAU") == 0)  Keyboard.write(KEY_PAUSE);

          delay(100);

        }

        else if (rcvString[1] == 'E') {

          if      (strcmp(addStr, "ESC") == 0)  Keyboard.write(KEY_ESC);

          else if (strcmp(addStr, "END") == 0)  Keyboard.write(KEY_END);

          else if (strcmp(addStr, "ENT") == 0)  Keyboard.write(KEYPAD_ENTER);

          delay(100);

        }

        else if (rcvString[1] == 'A') {

          if      (strcmp(addStr, "ArU") == 0)  Keyboard.write(KEY_UP_ARROW);

          else if (strcmp(addStr, "ArD") == 0)  Keyboard.write(KEY_DOWN_ARROW);

          else if (strcmp(addStr, "ArL") == 0)  Keyboard.write(KEY_LEFT_ARROW);

          else if (strcmp(addStr, "ArR") == 0)  Keyboard.write(KEY_RIGHT_ARROW);

          delay(100);

        }

        else {

          if      (strcmp(addStr, "TAB") == 0)  Keyboard.write(KEY_TAB);

          else if (strcmp(addStr, "RET") == 0)  Keyboard.write(KEY_RETURN);

          else if (strcmp(addStr, "BKS") == 0)  Keyboard.write(KEY_BACKSPACE);

          else if (strcmp(addStr, "HOM") == 0)  Keyboard.write(KEY_HOME);

          delay(100);

        }

      }

      // ----- combined keys

      else if (strcmp(rcvString, "AlTb") == 0)  AltTab();

      else if (strcmp(rcvString, "ShAT") == 0)  ShiftAltTab();

      // ---------------------------------------------------------------------- functions

      // ----- send info or not

      else if (strncmp(rcvString, "sOk", 3) == 0) sendOk = (rcvString[3] == '1');

      // ----- accept or not interrupt

      else if (strncmp(rcvString, "iOk", 3) == 0) intOk = (rcvString[3] == '1');

      // ----- load game #

      else if (strncmp(rcvString, "ld", 2) == 0)  loadGame(atoi(rcvString + 2));

      // ----- simple game

      else if (strcmp(rcvString, "SiGa") == 0)    simpleGame();

      // ----- harvest game

      else if (strcmp(rcvString, "HaGa") == 0)    harvestGame();

      // ----- quit FS

      else if (strcmp(rcvString, "qtGm") == 0)    {

        quitGame();

        forceReleaseButtons = true;

      }

      // ----- quit FS

      else if (strcmp(rcvString, "relb") == 0)    forceReleaseButtons = true;

      // ----- reset Arduino Due

      else if (strcmp(rcvString, "rstd") == 0)    RSTC->RSTC_CR = 0xA5000005;

      // ----- clear string

      strcpy(rcvString, "");

      nrcv = 0;

    }

  }

 

  // ----- reset speed

  if (sndStrFlag & bitAcc0) {

    analogWrite(out_forward, 0);

    analogWrite(out_bckward, 0);

  }

 

  // ----- Common loop PR/ PC / keyboard  (nCharPRList < nStrToSend < nCharWList)

  for (il = 0, jl = 1, kl = 1, ll = 2; il < nCharPRList; il++, jl <<= 1, kl <<= 2, ll <<= 2) {

    if (kbCharPR & kl) {

      // press key

      Keyboard.press(kbPRlist[il]);

      kbCharPR &= ~kl;

    }

    else if ((kbCharPR & ll)) {

      // release key

      Keyboard.release(kbPRlist[il]);

      kbCharPR &= ~ll;

    }

    if (sndStrFlag & jl) {

      // send Strings to PC

      sendSerial(strToSend[il]);

      sndStrFlag &= ~jl;

    }

    if (kbCharW & jl) {

      // chars to send (write) to keyboard

      Keyboard.write(kbWlist[il]);

      kbCharW &= ~jl;

    }

  }

 

  // ----- Common loop PC / keyboard  (nStrToSend < nCharWList)

  for (; il < nStrToSend; il++, jl <<= 1) {

    if (sndStrFlag & jl) {

      // send Strings to PC

      sendSerial(strToSend[il]);

      sndStrFlag &= ~jl;

    }

    if (kbCharW & jl) {

      // chars to send (write) to keyboard

      Keyboard.write(kbWlist[il]);

      kbCharW &= ~jl;

    }

  }

 

  // ----- remaining chars to write to keyboard

  for (; il < nCharWList; il++, jl <<= 1) {

    if (kbCharW & jl) {

      Keyboard.write(kbWlist[il]);

      kbCharW &= ~jl;

    }

  }

 

  // ----- special sequence to send to keyboard

  if (kbCharSeqFFF) {

    for (il = 0; il < 3; il++) Keyboard.write('F');

    kbCharSeqFFF = false;

  }

 

  if (kbCharSeqFFF5) {

    for (il = 0; il < 3; il++) Keyboard.write('F');

    delay(100);

    Keyboard.write(229);

    kbCharSeqFFF5 = false;

  }

 

  if (kbCharSeqFFF6) {

    for (il = 0; il < 3; il++) Keyboard.write('F');

    delay(100);

    Keyboard.write(230);

    kbCharSeqFFF6 = false;

  }

 

  if (kbCharSeq5F5) {

    Keyboard.write(229);

    delay(100);

    Keyboard.write('F');

    delay(100);

    Keyboard.write(229);

    kbCharSeq5F5 = false;

  }

 

  if (kbCharSeq6F6) {

    Keyboard.write(230);

    delay(100);

    Keyboard.write('F');

    delay(100);

    Keyboard.write(230);

    kbCharSeq6F6 = false;

  }

 

  if (kbCharSeq56F56) {

    Keyboard.write(229);

    delay(100);

    Keyboard.write(230);

    delay(100);

    Keyboard.write('F');

    delay(100);

    Keyboard.write(229);

    delay(100);

    Keyboard.write(230);

    kbCharSeq56F56 = false;

  }

 

  if (forceReleaseButtons) {

    // release all buttons

    oldSendOk = sendOk;

    sendOk = true;

    if (hornOn)         _hornOff();

    if (beaconOn)       _beacon();

    if (warningOn)      _WarningOff();

    if (Li_fr_down)     _lght_fr_low();

    if (Li_re_down)     _lght_re_low();

    if (Li_fr_up)       _lght_fr_up();

    if (Li_re_up)       _lght_re_up();

    if (leftBlinkerOn)  _leftBlinkOff();

    if (rightBlinkerOn) _rightBlinkOff();

    if (zoomInOn)       _zoomInOff();

    if (zoomOutOn)      _zoomOutOff();

    if (cameraOn)       _setCamera();

    forceReleaseButtons = false;

    releaseCnt = 1;

  }

 

  // check delta time to send data

  t1 = millis();

  okToSend = ((unsigned long)(t1 - t0) >= dt); // cast to avoid to manage roll-over

 

  // check if horn not blocked

  if (hornOn && ((unsigned long)(t1 - tHorn0) >= dtHorn)) forceReleaseButtons = true;

 

  // ------------------------------------------ Steering Wheel

  // read from ADC (0.1 to 3.2)

  curStwVal = myMap(analogRead(in_steeringW), 124, 3971);

  // write to DAC

  if (curStwVal != prevStwVal) {

    analogWrite(out_steeringW, curStwVal);

    prevStwVal = curStwVal;

    curStwAngle = map(curStwVal, 0, maxV12, -30, 30);

    if ((curStwAngle != prevStwAngle) && (okToSend)) {

      sprintf(sndString, "1STW%d", curStwAngle); // + offset ?

      sendSerial(sndString);

      prevStwAngle = curStwAngle;

    }

  }

 

  // ------------------------------------------ Accel

  // read from ADC (accel pedal max value is 2.4 V instead of 3.2)

  if ((!brakesOn) && (Direction != 0)) {

    accelPedal = myMap(analogRead(in_acc_pedal), 124, 2966);

    accelHand  = myMap(analogRead(in_acc_hand),  124, 2225);

    curAccel = max(accelPedal, accelHand);

    // write to DAC

    if (curAccel != prevAccel) {

      prevAccel = curAccel;

      if      (Direction ==  1) analogWrite(out_forward, curAccel);

      else if (Direction == -1) analogWrite(out_bckward, curAccel);

      curAccel2 = map(curAccel, 0, maxV12, 0, 100);

      if ((curAccel2 != prevAccel2) && (okToSend)) {

        sprintf(sndString, "1ACC%.2f", min(1.05 * float(curAccel2) / 100., 1.));

        sendSerial(sndString);

        prevAccel2 = curAccel2;

      }

    }

  }

 

  // ------------------------------------------ brakes

  curBrksVal = myMap(analogRead(in_brakes), 124, 3971);

  if (curBrksVal != prevBrksVal) {

    prevBrksVal = curBrksVal;

    analogWrite(out_brakes, curBrksVal);

    if ((curBrksVal < 820) && (brakesOn)) {

      sendSerial((char *)"2BRK0");

      brakesOn = false;

    }

    else if ((curBrksVal > 1230) && (!brakesOn)) {

      sendSerial((char *)"2BRK1");

      // reset speed

      sndStrFlag  |= bitAcc0;

      brakesOn = true;

    }

  }

 

  if (okToSend) t0 = t1;

 

  if (releaseCnt) {

    // count the nb of loop: be sure we made 1 loop at least

    releaseCnt += 1;

    if (releaseCnt == 3) {

      // we are sure here that the buttons were released

      releaseCnt = 0;

      sendOk = oldSendOk;

    }

  }

}

// ======================================================================================

//                    INTERRUPTIONS

// ======================================================================================

// ---------------------------------------------- pin_PosN_0 & pin_PosN_1 & pin_BP4_N

void _posN() {

  if (intOk) kbCharW |= bitKeyB;     // PosN -> 'B'

}

// ---------------------------------------------- pin_Horn

void _hornOn() {

  if (intOk) {

    attachInterrupt(pin_Horn, _hornOff, FALLING);

    hornOn = true;

    tHorn0 = millis();

    kbCharPR |= bitKey0Press;     // Horn -> '0'  HOLD

  }

}

void _hornOff() {

  kbCharPR |= bitKey0Release;       // Horn -> '0'  RELEASE

  hornOn = false;

  attachInterrupt(pin_Horn, _hornOn, RISING);

}

// ---------------------------------------------- pin_Beacon

void _beacon() {

  if (intOk) {

    kbCharW |= bitKeyHome ;           // 'HOME'

    beaconOn = !beaconOn;

    strToSend[nStrBeacon][4] = char(48 + int(beaconOn));

    sndStrFlag |= bitBeacon;

  }

}

// ---------------------------------------------- pin_SeqLev_PB

void _act_o() {

  if (intOk) kbCharW |= bitKeyO;       // action -> 'O'

}

// ---------------------------------------------- pin_RightBlinker

void _rightBlinkOn() {

  if (intOk) {

    attachInterrupt(pin_RightBlinker, _rightBlinkOff, FALLING);

    kbCharW |= bitKP3;            // KP3 -> 227

    strToSend[nStrRightBlinker][4] = '1';

    rightBlinkerOn = true;

    sndStrFlag |= bitRightBlinker;

  }

}

void _rightBlinkOff() {

  kbCharW |= bitKP3;              // KP3 -> 227

  strToSend[nStrRightBlinker][4] = '0';

  sndStrFlag |= bitRightBlinker;

  rightBlinkerOn = false;

  attachInterrupt(pin_RightBlinker, _rightBlinkOn, RISING);

}

// ---------------------------------------------- pin_LeftBlinker

void _leftBlinkOn() {

  if (intOk) {

    attachInterrupt(pin_LeftBlinker, _leftBlinkOff, FALLING);

    kbCharW |= bitKP1;            // KP1 -> 225

    strToSend[nStrLeftBlinker][4] = '1';

    leftBlinkerOn = true;

    sndStrFlag |= bitLeftBlinker;

  }

}

void _leftBlinkOff() {

  kbCharW |= bitKP1;              // KP1 -> 225

  strToSend[nStrLeftBlinker][4] = '0';

  sndStrFlag |= bitLeftBlinker;

  leftBlinkerOn = false;

  attachInterrupt(pin_LeftBlinker, _leftBlinkOn, RISING);

}

// ---------------------------------------------- pin_Warning

void _WarningOn() {

  if (intOk) {

    attachInterrupt(pin_Warning, _WarningOff, FALLING);

    kbCharW |= bitKP2;            // KP2 -> 226

    strToSend[nStrWarning][4] = '1';

    warningOn = true;

    sndStrFlag |= bitWarning;

  }

}

void _WarningOff() {

  kbCharW |= bitKP2;              // KP2 -> 226

  strToSend[nStrWarning][4] = '0';

  sndStrFlag |= bitWarning;

  warningOn = false;

  attachInterrupt(pin_Warning, _WarningOn, RISING);

}

// ---------------------------------------------- pin_Li_FrUp

void _lght_fr_up() {

  if (intOk) {

    Li_fr_up = !Li_fr_up;

    strToSend[nStrLghtFrUp][4] = char('0' + int(Li_fr_up));

    sndStrFlag |= bitLghtFrUp;

    kbCharW |= bitKP5;            // KP5 -> 229

  }

}

// ---------------------------------------------- pin_Li_FrDown

void _lght_fr_low() {

  if (intOk) {

    Li_fr_down = !Li_fr_down;

    strToSend[nStrLghtFrUp][4] = char('0' + int(Li_fr_up));

    sndStrFlag |= bitLghtFrDown;

    boolean Li_re = Li_re_up || Li_re_down;

    if (Li_fr_down) {

      if (Li_fr_up && Li_re) kbCharSeq56F56 = true;

      else if (Li_fr_up)     kbCharSeq5F5 = true;

      else if (Li_re)        kbCharSeq6F6 = true;

      else                   kbCharW |= bitKeyF;

    }

    else {

      if (Li_fr_up != Li_re)  kbCharSeqFFF = true;

      else if (Li_fr_up)      kbCharSeqFFF5 = true;

      else                    kbCharSeqFFF6 = true;

    }

  }

}

// ---------------------------------------------- pin_Li_ReUp

void _lght_re_up() {

  if (intOk) {

    Li_re_up = !Li_re_up;

    strToSend[nStrLghtReUp][4] = char('0' + int(Li_re_up));

    sndStrFlag |= bitLghtReUp;

    if (! Li_re_down) kbCharW |= bitKP6;            // KP6 -> 230

  }

}

// ---------------------------------------------- pin_Li_ReDown

void _lght_re_low() {

  if (intOk) {

    Li_re_down = !Li_re_down;

    strToSend[nStrLghtReUp][4] = char('0' + int(Li_re_up));

    sndStrFlag |= bitLghtReDown;

    if (! Li_re_up) kbCharW |= bitKP6;            // KP6 -> 230

  }

}

// ---------------------------------------------- pin_UTurn

void _u_turn() {

  if (intOk) kbCharW |= bitKeyG;       // 'G'

}

// ---------------------------------------------- pin_LG_Up

void _lg_up() {

  if ((intOk) && (!Lg_up)) {

    kbCharW |= bitKeyV;           // 'V'

    Lg_up = true;

  }

}

// ---------------------------------------------- pin_LG_Down

void _lg_down() {

  if ((intOk) && (Lg_up)) {

    kbCharW |= bitKeyV;           // 'V'

    Lg_up = false;

  }

}

// ---------------------------------------------- pin_HydrauLeftLeverFrwd

void _hydLeftFwd() {

  if (intOk) kbCharW |= bitKeyX;           // 'X'

}

// ---------------------------------------------- pin_HydrauLeftLeverBkwd

void _hydLeftBwd() {

  if (intOk)  kbCharW |= bitKeyX;           // 'X'

}

// ---------------------------------------------- pin_HydrauRightLeverFrwd

void _hydRightFwd() {

  if (intOk)  kbCharW |= bitKeyI;           // 'I'

}

// ---------------------------------------------- pin_HydrauRightLeverBkwd

void _hydRightBwd() {

  if (intOk) kbCharW |= bitKeyI;           // 'I'

}

// ---------------------------------------------- pin_GreenButtonLeftJS

void _setCamera() {

  cameraOn = !cameraOn;

  if (intOk) kbCharW |= bitKeyC;         // 'C'

}

// ---------------------------------------------- pin_RedButtonLeftJS

void _hideshowpan() {

  if (intOk) kbCharW |= bitKeyBS;      // 'BS'

}

// ---------------------------------------------- pin_GreenButtonRightJS

void _zoomOutOn() {

  if (intOk) {

    attachInterrupt(pin_GreenButtonRightJS, _zoomOutOff, FALLING);

    zoomOutOn = true;

    kbCharPR |= bitKeyPgUpPress;      // zoomOut -> 'PgUp'  HOLD

  }

}

void _zoomOutOff() {

  kbCharPR |= bitKeyPgUpRelease;        // zoomOut -> 'PgUp'  RELEASE

  zoomOutOn = false;

  attachInterrupt(pin_GreenButtonRightJS, _zoomOutOn, RISING);

}

// ---------------------------------------------- pin_RedButtonRightJS

void _zoomInOn() {

  if (intOk) {

    attachInterrupt(pin_RedButtonRightJS, _zoomInOff, FALLING);

    zoomInOn = true;

    kbCharPR |= bitKeyPgDwnPress;     // zoomIn -> 'PgDown' HOLD

  }

}

void _zoomInOff() {

  kbCharPR |= bitKeyPgDwnRelease;       // zoomOut -> 'PgDown'  RELEASE

  zoomInOn = false;

  attachInterrupt(pin_RedButtonRightJS, _zoomInOn, RISING);

}

// ---------------------------------------------- pin_FrwdInfo

void _forwardOn() {

  attachInterrupt(pin_FrwdInfo, _forwardOff, FALLING);

  setDirection(1);

}

void _forwardOff() {

  setDirection(0);

  attachInterrupt(pin_FrwdInfo, _forwardOn, RISING);

}

// ---------------------------------------------- pin_BkwdInfo

void _backwardOn() {

  attachInterrupt(pin_BkwdInfo, _backwardOff, FALLING);

  setDirection(-1);

}

void _backwardOff() {

  setDirection(0);

  attachInterrupt(pin_BkwdInfo, _backwardOn, RISING);

}

// ---------------------------------------------- pin_FrwdBkwdToggle

void _toggleDir() {

  if (Direction == 0) Direction = -1 ;

  setDirection(-Direction);

}

// ---------------------------------------------- pin_A

void _attach() {

  if (intOk) kbCharW |= bitKeyA;      // 'A'

}

__________________________________________________________________________

 

 

 

2/ Arduino UNO (attached to "Master" PC)

 

Nothing very special to notice... It's a quite simple program.

 

 

inputsUNO.c  _______________________________________________________________

/*

Program Arduino UNO

Manage relays for Farming Simulator

Damien Hallez, nov 2017

*/

 

// ----- pins for Raspberry's

const short RPi_Out  = 0;

const short RPi_Disp = 1;

const short RPi_Pres = 2;

const short Supply15 = 3;

short Rpi_pins[] = {10, 11, 12, 13};

 

// ----- Sound relays (high current)

short Sound_pins[] = {8, 9};

 

// pin for reset DUE

const short pin_resetDue = 3;

// ----- Serial -> pins 18 & 19

 

// Cylinders orders

const short Order1 = 0;

const short Order2 = 1;

const short Order3 = 2;

const short Order4 = 3;

short Order_pins[] = {7, 6, 5, 4};

 

const short pin_TireUp   =  2 ;    // ---- Tire Up info

 

// ----- boolean to send

volatile boolean sendTireUp = false;

 

char rcvString[10] ;

int nrcv = 0;

 

// ======================================================================================

//                    SETUP

// ======================================================================================

void setup() {

  // -------------------------------------------- Serial (makes a reset !!)

  Serial.begin(115200);

 

  // -------------------------------------------- Relays

  // ----- output pins for sound relays

  for (short i=0; i<2; i++) pinMode(Sound_pins[i], OUTPUT);

  sndRelays(0);

 

  // ----- output pins for Rpi's relays

  for (short i=0; i<4; i++) pinMode(Rpi_pins[i], OUTPUT);

  rpiRelays('a', 0);

  setSupply(1);

 

  // ----- output pins for cylinders orders' relays

  for (short i=0; i<4; i++) pinMode(Order_pins[i], OUTPUT);

  orderRelays(0);

 

  // reset DUE

  pinMode(pin_resetDue, OUTPUT);

  digitalWrite(pin_resetDue, HIGH);

 

  // attach an interrupt to the tire Up info

  attachInterrupt(digitalPinToInterrupt(pin_TireUp), _TireUp, RISING);

 

  // ----- wait for serial PC

  while (!Serial);

}

 

// ======================================================================================

//                    SUBROUTINES

// ======================================================================================

// ----- send strings to the serial link

void sendSerial(char *txt) {

  if (Serial.availableForWrite() > strlen(txt)) {

    Serial.println(txt); // println add '\r\n' to the string

  }

}

 

// ----- relays sound

void sndRelays(short onOff) {

  for (short i=0; i<2; i++) digitalWrite(Sound_pins[i], onOff);

}

 

// ----- relays RPi's

void rpiRelays(char nr, short onOff) {

  if (nr == 'a') {

    for (short i=0; i<3; i++) digitalWrite(Rpi_pins[i], 1-onOff);

  }

  else digitalWrite(Rpi_pins[nr-'0'], 1-onOff);

}

 

// ----- set 15v supply

void setSupply(short onOff) {

  digitalWrite(Rpi_pins[Supply15], 1-onOff);

}

 

// ----- relays orders

void orderRelays(short nr) {

  if (nr == 0){

      for (short i=0; i<4; i++) digitalWrite(Order_pins[i], 1);

  }

  else {

      for (short i=1; i<5; i++) {

          if (i == nr) digitalWrite(Order_pins[i-1], 0);

          else         digitalWrite(Order_pins[i-1], 1);

      }

  }

}

 

void resetDue() {

  digitalWrite(pin_resetDue, LOW);

  delay(500);

  digitalWrite(pin_resetDue, HIGH);

}

// ======================================================================================

//                    MAIN LOOP

// ======================================================================================

void loop() {

  // ------------------------------------------  commands read from serial input

  while (Serial.available()) {

    char inChar = (char)Serial.read();

    rcvString[nrcv++] = inChar;

    if (inChar == '\n') {

      rcvString[strcspn(rcvString, "\r\n")] = 0;

      // for DEBUG Serial.println(rcvString);

      // snd{0|1}, rpi{0|1|2|a}{0|1}, rstd, ord{0|1|2|3}, sup{0|1}

      if      (strncmp(rcvString, "snd", 3) == 0) sndRelays(rcvString[3] - '0');

      else if (strncmp(rcvString, "rpi", 3) == 0) rpiRelays(rcvString[3], rcvString[4] - '0');

      else if (strncmp(rcvString, "sup", 3) == 0) setSupply(rcvString[3] - '0');

      else if (strncmp(rcvString, "ord", 3) == 0) orderRelays(rcvString[3] - '0');

      else if (strcmp(rcvString, "rstd") == 0)  resetDue();

      else if (strcmp(rcvString, "rstu") == 0) {

        setSupply(1);

        sndRelays(0);

        rpiRelays('a', 1);

        orderRelays(0);

      }

      else if (strcmp(rcvString, "shtd") == 0) {

        sndRelays(0);

        rpiRelays('a', 0);

        orderRelays(0);

        setSupply(0);

      }

      strcpy(rcvString, "");

      nrcv = 0;

    }

  }

  if (sendTireUp) {

    sendSerial((char *)"TiUp");

    sendTireUp = false;

  }

}

 

// ======================================================================================

//                    INTERRUPTIONS

// ======================================================================================

// ---------------------------------------------- pin_PosN_0 & pin_PosN_1 & pin_BP4_N

void _TireUp() {

  sendTireUp = true;     // set flag to true

}

__________________________________________________________________________

 

Back to intro

Tractor Simulator (interface with Farming Simulator 17)

 

Global presentation

Tractor simulator (cabin tractor interface with Farming Simulator 17): Part 1 - global presentation

 

The hardware

Tractor simulator (cabin tractor interface with Farming Simulator 17): Part 2 - the hardwareTractor simulator (cabin tractor interface with Farming Simulator 17): Part 2 - the hardware

 

Actual doc

 

Raspberry Pis

Tractor simulator (cabin tractor interface with Farming Simulator 17): Part 3 - the software, 2/ Raspberrys

 

PCs

Tractor simulator (cabin tractor interface with Farming Simulator 17): Part 3 - the software, 3/ PCs