Arduino Remote Control

Anything Arduino

Arduino Remote Control

Postby Tim Laren » Wed Nov 07, 2012 12:50 am

I have been using Bluetooth to control my Robotic Car for demos and teaching. Problem is my phone is the only thing I have with Bluetooth on it so I have to let everyone play with my phone if I want them to control the car.

Image
I decided to use an Arduino UNO http://hacker.instanet.net/Store/arduino-uno-r3-p-69.html, the LCD Keypad Shield http://hacker.instanet.net/Store/lcd-keypad-shield-p-59.html and a MiRF Module (nRF24L01) http://hacker.instanet.net/Store/nrf24l01-wireless-transceiver-module-24ghz-10-pin-p-2.html. It actually went together fairly simply. Here is the process and code to do it yourself.

My LCD Keypad Shield has all the unused pins brought out to the edge of the board.
Image
The pins here are on the bottom edge of the board and I used Ground and 3.3V (The MiRF module required 3.3 Volts for it's power, not 5 Volts.)

I soldered on pins pointing downward where I needed to connect to these signals. I am using the SPI port pins to connect to the MiRF Module. The required pins are on the top edge of the board. On the UNO the SPI is as follows: SCK - 13, MISO - 12, MOSI - 11 SS - 10 (leave open). The MiRF also requires two other enable signals, where I used pin 2 for CE and pin 3 for CS. On the bottom edge I connected to power and ground.

The pins on the bottom edge are as follows: RST, 3.3V, 5V, GND, GND and VIN on the first connector and A1, A2, A3, A4 and A5 on the second connector. The pins on the top edge are as follows: 13, 12, 11, 3, 2, 1 and 0.

Image
Here is how I wired to the LCD Keypad Shield on the top and bottom edges and then I ran the cable between the shield and Arduino.

Image
Here is a close-up of the MiRF connected to my cable. The cable I used an 8 pin cable with the following colors: Yellow, Orange, Red, Brown, Black, White, Gray and Violet. I used Red for 3.3V and Black for Ground. Violet - CE, Gray - CS White - SCK, Yellow - MISO, Orange - MOSI. This just happened to be the cable I had sitting around so if you make your own just make sure the right pins go to the right place.http://hacker.instanet.net/Store/solderless-breadboard-jumper-wire-kit-mf-p-80.html

You may note the square of double backed tape on the back of the MiRF module, this is used to connect the module to the edge of the LCD screen.
Image

I have used the MiRF Modules before but now with Arduino 1.0(.1) they seem to no longer work. The new Arduino IDE includes a SPI Library that is not compatible with my old code. I did a little searching and found the RF24 library. I have attached the version I used to this post. You will also require a library for the LCD Display. I used the standard library included with the Arduino IDE.
Lets start coding. First we need to include the SPI, nRF24L01 and LCD libraries:
Code: Select all
// nRF24L01 Linrary stuff
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

// LCD library
#include <LiquidCrystal.h>

Note there is a printf library also, this allows us to print multiple items per a print statement and format them using standard 'C' formatting conventions.

Next we have to create a radio and LCD Display:
radio(2,3) defines what pins for CE and CS.
lcd(8, 9, 4, 5, 6, 7) define the CS, E and 4 data lines.
Code: Select all
// Create a radio
RF24 radio(2,3);
// Create an LCD
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


msgs holds messages to print when a key is pressed.
adc_key_vals holds the analog values for each push button.
NUM_KEYS is how many keys to scan for.
KeyPad is the Analog pin to read for the keypad.
The next few are used to store the key values and de-bounce the keys.
Code: Select all
//Key message
char msgs[5][15] = {"Right    ",
                    "Forward  ",
                    "Backward ",
                    "Left     ",
                    "Stop     " };
int  adc_key_val[5] ={30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int KeyPad = A0;
int adc_key_in;
int key = -1;
int oldkey = -1;
int LastCin = 0;


Next we are on to the setup:
Initialize Serial and printf libraries
Code: Select all
void setup(void)
{
  Serial.begin(9600);
  printf_begin();

Setup for 16X2 LCD, clear the display and print our welcome message to the LCD and Serial
Code: Select all
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print(" CD-Bot Control");
  printf("CD-Bot Control\n\r");

Start the radio
Code: Select all
  radio.begin();

Adjust the Retries and reduce the payload for less errors and better range
Code: Select all
  // optionally, increase the delay between retries & # of retries
  radio.setRetries(15,15);
  // optionally, reduce the payload size.  seems to improve reliability
  radio.setPayloadSize(8);

Open pipes for reading and writing. A pipe connects two radios, one for sending and one for receiving.
We then turn on the receiver. We also post some misc stuff to the serial port for debugging with the printDetails() function.
Code: Select all
  //
  // Open pipes to other nodes for communication
  //
  radio.openReadingPipe(0,0xF0F0F0F0D2LL);
  radio.openWritingPipe(0x3A3A3A3AD2LL);
  radio.startListening();
  radio.printDetails();
}

That's all for the startup and now we are onto the main loop
Code: Select all
void loop(void)
{
  int Cin = Key();
  if(Cin != -1)
We get a value from the keypad, if it is -1 (255) then we got nothing pressed.
Code: Select all
  {
    if(Cin != LastCin)
    {
Got a new keypress, not the same as last time
Code: Select all
      lcd.setCursor(15,2);
      lcd.print(Cin);
      LastCin = Cin;
      lcd.setCursor(1,2);
      lcd.print(msgs[Cin]);
Print the keycode on the bottom right of screen and the function on the left bottom line
Code: Select all
      switch(Cin)
      {
        case 0:
          Send('R');
          break;
        case 1:
          Send('F');
          break;
        case 2:
          Send('B');
          break;
        case 3:
          Send('L');
          break;
        case 4:
          Send('S');
          break;
Send one of the Commands over the link: F(orwards), B(ackwards), L(eft), R(ight) and S(top)
Code: Select all
      }
    }
  }
}


I'm sure that if you loaded the sketch you noticed there are several files including LCD and Radio (and printf.h). These are routines that I felt I may use other placed so I put them in separate files so I can reuse them later. Here is LCD:
Read a key
Code: Select all
int Key()
{
  key = get_key(analogRead(KeyPad));          // read key value and convert into key press
  if(key == -1) return key;
Get a key, if nothing then return -1
Code: Select all
  if (key != oldkey)                  // if keypress is detected
  {
    delay(50);                        // wait for debounce time
    key = get_key(analogRead(KeyPad));          // read key value and convert into key press
Wait a little bit and re-read the keys
Code: Select all
    if (key != oldkey)
    {
      oldkey = key;
      return key;
If the same key is presses, return that code
Code: Select all
    }
  }
  return -1;
}
Else return -1, no key pressed.

Code: Select all
// Convert ADC value to key number
int get_key(unsigned int input){
  int k;
  for (k = 0; k < NUM_KEYS; k++){
    if (input < adc_key_val[k]){
      return k;
    }
  }   
Find a range for each keypress
Code: Select all
  if (k >= NUM_KEYS)  k = -1;     // No valid key pressed
  return k;
}
If no match, return no key pressed.

The radio routines. First Receive but we don't use it with this sketch
Code: Select all
char Receive()
{
  char command = ' ';
  if ( radio.available() )
  {
If there is data available from the radio
Code: Select all
    bool done = false;
    while (!done)
    {
      done = radio.read( &command, sizeof(command) );
      printf("Got payload %c...", command);
      delay(20);
    }
read till we empty the buffer
Code: Select all
    radio.stopListening();
turn off the receiver
Code: Select all
    radio.write( &command, sizeof(command) );
    printf("Sent response.\n\r");
Send back the command as an acknowledgement
Code: Select all
    radio.startListening();
  }
Turn back on the receiver
Code: Select all
  return command;
}

Send function:
Code: Select all
char Send(char Cmd)
{
    radio.stopListening();
Turn off the receiver
Code: Select all
    radio.write( &Cmd, sizeof(Cmd) );
    printf("Sent command %c.\n\r", Cmd);
Send the command and print to serial
Code: Select all
    radio.startListening();
Turn on the receiver
Code: Select all
}


ACK Function, not used in this sketch
Code: Select all
void ack(char cmd)
{
  radio.stopListening();
  bool ok = radio.write( &cmd, sizeof(cmd) );
Turn off receiver and send command
Code: Select all
  if (ok)
  {
    printf("ok...");
  }
  else
  {
    printf("failed.\n\r");
  }
Print status of transmition
Code: Select all
    radio.startListening();
}
Turn back on the receiver.

If you load the sketch and use the serial monitor you should get good values when the radio is initialized.
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xf0f0f0f0d2 0x3a3a3a3ac3
RX_ADDR_P2-5 = 0xb4 0xc4 0xc5 0xc6
TX_ADDR = 0x3a3a3a3ad2
RX_PW_P0-6 = 0x08 0x08 0x08 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x07
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0f
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_HIGH
If you find that all or most values are 0, then you most likely have your wiring wrong or no power to the MiRF Module.

If you are still with me here and are getting none zero results on the printDetails display, then you are finished. When you press key on the keypad you should get changes on the display to confirm these button presses. The next step is to build something to control. My next article.
Attachments
CD-Bot_Control.zip
Arduino Remote Control Sketch.
(2.72 KiB) Downloaded 459 times
RF24.zip
RF24 Library
(203.43 KiB) Downloaded 438 times
Image
Tim Laren
Site Admin
 
Posts: 137
Joined: Thu Mar 04, 2010 8:25 pm

Re: Arduino Remote Control

Postby Dr_Bundolo » Thu Oct 11, 2018 1:13 pm

Hi Tim:
I'm writing about a project you posted a LONG time ago. Of course since then things have changed. I'm trying to get it working but I'm getting keypad errors. Could be some of the libraries (besides the NRF24101) have changed.
Here's the initial error I'm receiving:
Arduino: 1.8.5 (Windows 10), Board: "Arduino/Genuino Uno"

C:\Users\Jeffrey\AppData\Local\Temp\arduino_modified_sketch_658182\CD_Bot_Control.ino: In function 'void loop()':

CD_Bot_Control:62: error: 'Key' was not declared in this scope

int Cin = Key();

^

CD_Bot_Control:76: error: 'Send' was not declared in this scope

Send('R');

^

Can you offer any help?
Thanks
Jeff
Dr_Bundolo
 
Posts: 1
Joined: Thu Oct 11, 2018 1:02 pm

Re: Arduino Remote Control

Postby Tim Laren » Thu Oct 11, 2018 1:38 pm

I would need to see all the code.
Maybe you could zip it up and upload it.
Or just email it to me.
Unless it is not been changed and you are using the above code?

Tim
Image
Tim Laren
Site Admin
 
Posts: 137
Joined: Thu Mar 04, 2010 8:25 pm


Return to Arduino

Who is online

Users browsing this forum: No registered users and 1 guest

cron