Showing posts with label Arduino. Show all posts
Showing posts with label Arduino. Show all posts

March 2, 2019

Simple FlySky i6 Arduino Robot Code (WIP)

The following code is a basic Arcade Drive style of code that uses the FlySky i6 hobby controller. The radio controller is not naturally mated to the Arduino coding language, however, the radio transmitter that comes with the controller can be used with the Arduino platform with just a few simple coding workarounds. Additionally, you will notice that this code does not require any additional libraries in order to work. The code is written in a class format which allows simple upfront coding, with the advantage of more usability inside the specific classes.

NOTE 1: THIS IS STILL VERSION 0.1 OF THE CODE AS OF THE MOMENT IT HAS NOT BEEN TESTED WITH AN ACTUAL BOT (as my team has yet to give me a bot to code)
NOTE 2: FURTHER CODE UPDATES WILL BE POSTED AT THIS LOCATION, SO THE CODE YOU SEE NOW MAY NOT BE THE CODE YOU SEE NEXT.
NOTE 3: THIS CODE UTILIZES A H-BRIDGE MOTOR CONTROLLER

/*
  2019 Beetleweight Class Robot Code
  Tri-C
  Version: 0.1 Testing
  Dan Jira
  3/1/2019
  jiratheman@gmail.com
  dan-jira.blogspot.com 
*/

class TestCode
{
  public:
    static void Setup();
    static void Loop();
    
  private:
    // Member Functions
    static void ArcadeDriveFSi6();
    static void TankDriveFSi6();
    static void SetMotorValues(double leftOutput, double rightOutput);
  
    // Constants
      // For Controller
    static const bool           USE_FS_I6_CONTROLLER          =  true;
    static const unsigned       FS_I6_SWITCH_THRESHOLD_VALUE  =  1500;
    static const unsigned long  PULSE_IN_TIMEOUT_US           = 50000;
    
      // For H-Bridge
    static const unsigned int   H_BRIDGE_ENA                  =     3;
    static const unsigned int   H_BRIDGE_IN1                  =     5;
    static const unsigned int   H_BRIDGE_IN2                  =     6;
    static const unsigned int   H_BRIDGE_IN3                  =     7;
    static const unsigned int   H_BRIDGE_IN4                  =     8;
    static const unsigned int   H_BRIDGE_ENB                  =     9;
    
      // For Unknown (commented out for now)
  //static const unsigned int   NANO_MOVE_LEFT_PIN            =    10;
  //static const unsigned int   NANO_MOVE_RIGHT_PIN           =    11;
    
      // For Controller Channel Input Pins (need Mega)
    static const unsigned int   CH1_INPUT_PIN                 =    48;
    static const unsigned int   CH2_INPUT_PIN                 =    49;
    static const unsigned int   CH3_INPUT_PIN                 =    50;
    static const unsigned int   CH4_INPUT_PIN                 =    51;
    static const unsigned int   CH5_INPUT_PIN                 =    52;
    static const unsigned int   CH6_INPUT_PIN                 =    53;
};

//////////////////////////////////////////////////////////////////////
///
/// Method: Setup
///
/// Details: The Arduino initialization function called during
///          controller start up.
//////////////////////////////////////////////////////////////////////

void setup()
{
  TestCode::Setup();
}

//////////////////////////////////////////////////////////////////////
///
/// Method: Loop
///
/// Details: Keeps the Arduino running, uses called code and
///          functions.
//////////////////////////////////////////////////////////////////////

void loop()
{
  TestCode::Loop();
}

///////////////////////////////////////////////////////////////////////
///
/// Method: Setup
///
/// Description: Initialize TestCode function
///
///////////////////////////////////////////////////////////////////////

void TestCode::Setup()
{
  // Final declaration of variables
  const unsigned int ONE_SECOND_DELAY_MS  = 1000;
  
  // Begin Serial monitor @ 115200baud
  Serial.begin(115200);
  Serial.println("Test Code.");
  
  // Check for controller
  if (USE_FS_I6_CONTROLLER)
  {
    // Set pins for controller inputs
    pinMode(CH1_INPUT_PIN, INPUT);
    pinMode(CH2_INPUT_PIN, INPUT);
    pinMode(CH3_INPUT_PIN, INPUT);
    pinMode(CH4_INPUT_PIN, INPUT);
    pinMode(CH5_INPUT_PIN, INPUT);
    pinMode(CH6_INPUT_PIN, INPUT);
    Serial.println("FlySky i6 Controller.");
  } else {
    // Warn for no controller
    Serial.println("No controller configured.");
  }
  
  // H-Bridge outputs
  pinMode(H_BRIDGE_ENA, OUTPUT);
  pinMode(H_BRIDGE_IN1, OUTPUT);
  pinMode(H_BRIDGE_IN2, OUTPUT);
  pinMode(H_BRIDGE_IN3, OUTPUT);
  pinMode(H_BRIDGE_IN4, OUTPUT);
  pinMode(H_BRIDGE_ENB, OUTPUT);
  
  // Commented out until I learn more
  //pinMode(NANO_MOVE_LEFT_PIN,  INPUT);
  //pinMode(NANO_MOVE_RIGHT_PIN, INPUT);
}

///////////////////////////////////////////////////////////////////////
///
/// Method: Loop
///
/// Description: Test Code main loop
///
///////////////////////////////////////////////////////////////////////

void TestCode::Loop()
{
  // I think this is for extra sensors we aren't using
  // May be deleted
  //static bool bWasAuto    = false;
  //static bool bWasManual  =  true;
  //static bool bReadCenter =  true;
  
  // Select preferred driving mode by commenting out the unused one
  if (USE_FS_I6_CONTROLLER)
  {
    ArcadeDriveFSi6();
    //TankDriveFSi6();
  } else {
    // If no controller warn user through SM
    Serial.println("No Controller Connected!");
  }
}

///////////////////////////////////////////////////////////////////////
///
/// Method: ArcadeDriveFSi6
///
/// Description: Arcade drive style with FSi6 
///
///////////////////////////////////////////////////////////////////////

void TestCode::ArcadeDriveFSi6()
{
  // FSi6 Axis Inputs
    // X = Ch1
    // Y = Ch2
  //        2000
  //          |
  // 1000 --------- 2000
  //          |
  //        1000
  //
  
  // Base Values (yAxis may need to be CH3)
  double xAxis = pulseIn(CH1_INPUT_PIN, HIGH, PULSE_IN_TIMEOUT_US);
  double yAxis = pulseIn(CH2_INPUT_PIN, HIGH, PULSE_IN_TIMEOUT_US);
  
  // Serial Stuff for testing purposes
  int c1 = pulseIn(CH1_INPUT_PIN, HIGH, PULSE_IN_TIMEOUT_US);
  int c2 = pulseIn(CH2_INPUT_PIN, HIGH, PULSE_IN_TIMEOUT_US);
  int c3 = pulseIn(CH3_INPUT_PIN, HIGH, PULSE_IN_TIMEOUT_US);
  int c4 = pulseIn(CH4_INPUT_PIN, HIGH, PULSE_IN_TIMEOUT_US);
  int c5 = pulseIn(CH5_INPUT_PIN, HIGH, PULSE_IN_TIMEOUT_US);
  int c6 = pulseIn(CH6_INPUT_PIN, HIGH, PULSE_IN_TIMEOUT_US);
  Serial.println(c1);
  Serial.println(c2);
  Serial.println(c3);
  Serial.println(c4);
  Serial.println(c5);
  Serial.println(c6);
  Serial.println();
  delay(500);
  return;
  
  // How to pause controller
  if ((xAxis == 0.0) || (yAxis == 0.0))
  {
    // Controller Off
    return;
  }
  
  // Normalize numbers to make H-Bridge Happy
  xAxis = ((xAxis - 1500.0)/(500.0));
  yAxis = ((yAxis - 1500.0)/(500.0));
  
  // Calculate motor outputs
  double leftOutput  = xAxis + yAxis;
  double rightOutput = xAxis + yAxis;
  SetMotorValues(leftOutput, rightOutput);
  
  // Even more things for SM debugging
  Serial.println("L, R");
  Serial.print(leftOutput);
  Serial.println(", ");
  Serial.print(rightOutput);
  delay(500);
}

///////////////////////////////////////////////////////////////////////
///
/// Method: TankDriveFSi6
///
/// Description: Tank drive style with FSi6 
///
///////////////////////////////////////////////////////////////////////

void TestCode::TankDriveFSi6()
{
  // Coming Soon... Maybe
}

///////////////////////////////////////////////////////////////////////
///
/// Method: SetMotorValues
///
/// Description: Sends motor vals to H-Bridge 
///
///////////////////////////////////////////////////////////////////////

void TestCode::SetMotorValues(double leftOutput, double rightOutput)
{
  // Output trimmed to -1/+1 to make H-Bridge even happier
  leftOutput  = (abs(leftOutput)  > .10) ?  1.0 :  leftOutput;
  leftOutput  = (abs(leftOutput)  < .10) ? -1.0 :  leftOutput;
  rightOutput = (abs(rightOutput) > .10) ?  1.0 : rightOutput;
  rightOutput = (abs(rightOutput) < .10) ? -1.0 : rightOutput;
  
  // Limit output to be at least 10% power
  leftOutput  = (abs(leftOutput)  < .10) ?  0.0 :  leftOutput;
  rightOutput = (abs(rightOutput) < .10) ?  0.0 : rightOutput;
  
  // Scale up for analog reading and output
  leftOutput  *= 255.0;
  rightOutput *= 255.0;
  
  // Set H-Bridge IN pins to motor directions
  // NOTE: set up for 2 motors per side?
  // LEFT MOTOR(S)
  if (leftOutput >= 0.0)
  {
    // Do stuff when left  motor active
    digitalWrite(H_BRIDGE_IN1, HIGH);
    digitalWrite(H_BRIDGE_IN2,  LOW);
    // SM for Debug
    Serial.println("1H, 2L");
  } else {
    // Do stuff when right motor active
    digitalWrite(H_BRIDGE_IN1,  LOW);
    digitalWrite(H_BRIDGE_IN2, HIGH);
    // SM for Debug
    Serial.println("1L, 2H");
  }
  
  // RIGHT MOTOR(S)
  if (rightOutput >= 0.0)
  {
    digitalWrite(H_BRIDGE_IN3, HIGH);
    digitalWrite(H_BRIDGE_IN4,  LOW);
    // SM for Debug
    Serial.println("3H, 4L");
  } else {
    digitalWrite(H_BRIDGE_IN3,  LOW);
    digitalWrite(H_BRIDGE_IN4, HIGH);
    // SM for Debug
    Serial.println("3L, 4H");
  }
  
  // Analog Pulses don't like negatives
  // prolly too complicated heh silly computer
  leftOutput  = abs( leftOutput);
  rightOutput = abs(rightOutput);
  
  // Setup the H-Bridge to handle forward/reverse controls
  analogWrite(H_BRIDGE_ENA,  leftOutput);
  analogWrite(H_BRIDGE_ENB, rightOutput);
  
  // More SM stuff for Debugging
  Serial.println("Left Output: " );
  Serial.print( leftOutput);
  Serial.println("Right Output: ");
  Serial.print(rightOutput);
  delay(500);
}

November 27, 2017

Weekday Arduino Project #2

Decode IR Remote Buttons

The Project:
Decode the signals from an IR remote to use in other projects.

Pictures:

Why?:
For later projects, and to decode any of your IR remotes for later usability.

What you need:
  1. Arduino Uno Board
  2. 3 pin IR receiver
  3. IR remote
  4. Breadboard
  5. Arduino software

The Schematic:

The Code:
// Include all needed libraries
#include <IRLib.h>
#include <IRLibMatch.h>
#include <IRLibRData.h>
#include <IRLibTimer.h>

// Create a receiver object to listen on pin 11
IRrecv My_Receiver(6);

// Create a decoder object
IRdecode My_Decoder;

void setup()
{
  Serial.begin(9600);
  My_Receiver.enableIRIn();   // Start the receiver
}

void loop() {
// Continuously look for results. When you have them pass them to the decoder
  if (My_Receiver.GetResults(&My_Decoder)) {
    My_Decoder.decode();   // Decode the data
    My_Decoder.DumpResults(); // Show the results on serial monitor
    My_Receiver.resume(); // Restart the receiver
  }

}

The Library:
Feel free to contact me if you have any questions!


November 20, 2017

Weekday Arduino Project #1

LCD Screen Reads Out Servo Angle

The Project:
Create an Arduino project that steadily increases the angle of a servo, and prints the angle on an LCD screen.

Pictures:
Why?:
This is a tester for a long-term project that I am working on currently.

What you need:

  1. Arduino Uno board
  2. 16 pin 16x2 LCD screen
  3. 3 pin servo
  4. 10k ohm potentiometer
  5. 220 ohm resistor
  6. Breadboard
  7. Arduino software
The Schematic:

The Code:
// Include the library code:

#include <LiquidCrystal.h>
#include <Servo.h>

// Initialize the library by associating any needed LCD interface pin
// With the arduino pin number it is connected to
// Const ints
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
const int numRows = 2;
const int numCols = 16;

// Ints
int potpin = 0;
int val;
int count  = 0;

// Create servo object to control servo
Servo myservo;

// Set up LCD display
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
 // Set up the LCD's number of columns and rows:
 lcd.begin(numCols, numRows);
 Serial.begin(9600);
 myservo.attach(9);
}

Void loop(){
 // Refresh the display
 lcd.clear();
 lcd.display();
 // Set display
 lcd.setCursor(0,0);
 
 // Math for Servo
 count = (count + 1);
 Serial.print(count);
// Reset counter if it reaches 1000
 if (count == 1000){
   count = 0;
}
 // Convert and write to servo
 val = map(count,0,1000,0,180);
 myservo.write(val);
 
 // Print angle on LCD
 lcd.print(val);
 delay(50);
}

Feel free to contact me if you have any questions!