NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Sensors, Actuators, and Robotics » 2 Servos, 1 Analog Joystick

January 13, 2010
by Phrank916
Phrank916's Avatar

So, I'm brainstorming on projects and have been scouring the "intar-webs" for things I want to tackle in the future. One thing I'd like to attempt is something similar to this project which is currently on the front news page of Sparkfun:

Youtube Video - M&M Dispenser

Now, I don't want to be told how to do it, I know learning means doing it myself. So, I guess I'm posting here to "think aloud" if you will, and I do indeed welcome any suggestions or minor help where needed to help me fit the pieces together.

So here's my idea so far, along with information I have gathered from projects here and other things I've read and studied: I want to use the same analog joysick in the project above which I've found for cheap on Sparkfun. They also have a custom made breakout board for it, altogether about 5 bucks. The analog joystick is, if I recall, just two 10k potentiometers for each axis. I know I'll need to give power to the joystick and I'll have two leads from each axis pot going into 2 pins on the MCU. These pins will be set as inputs for the ADC. I'm unsure here on the math and the exact setting for the ADC but I'm pretty confident that with a pad of paper and the data sheets I'll be able to do the computations. I know the pots will be fed +5v and when turned back and forth that it will vary the output voltage. So, say it's a 0 to 5 range, then the middle would be 2.5, so I'm assuming when the joystick is at rest and centered that both axes will read 2.5V.

From this point I will need to take the digital data I get from the ADC which I know from the thermistor project, is 0-1023 sincne it's a 10-bit ADC. From this I'm again assuming that the centered reading would be 2.5v, giving me an output from both channels of the ADC of 512 when the jotstick is centered.

NEXT, I know I'm going to be driving two servos for each axis with two PWM channels (please correct me if I'm using the wrong "lingo"). I will take the data from the two ADC channels and do some fancy math to convert that to a figure that will be plugged into OCRnx to adjust the "compare value" up or down. This will also involve some fancy math to ensure the bottom end of the ADC range at zero is dropping the compare line down, while 512 is the center and 1023 is the top.

Ok, so I think that's pretty much the basic theory which I've put together in my head. My next plan is to get ahold of just a single hobby servo, which I think I can get for free from a friend of mine who is WAY into RC 4X4 trucks. With that I was thinking of doing some experimentation with the pot included in the USB NerdKit and see if I can't get the servo to move back and forth when the pot is moved back and forth. My main goal of this experiment is to get real-time responsiveness with an analog input source and not simply sending a digital signal to move the servo to left or right at a constant speed. I want to be able to move the joystick slow or fast and have the servo move slow or fast.

So, if after reading this it got your wheels turning, and you're aching to throw in your 2 cents, PLEASE DO SO! I welcome all feedback and advice.

Ted

January 13, 2010
by Rick_S
Rick_S's Avatar

Basic Idea is very good. Might want to check out the servo squirter tutorial here for servo programming ideas. I've used a joystick very similar to that one as an input for an avr and it centers around the halfway point but does not go to the full top and bottom (0 - 1023) I set up ranges in my application for varying degrees of movement and a "safe zone" at center.

Keep us updated... looks like an interesting project !!

Rick

January 13, 2010
by Phrank916
Phrank916's Avatar

Ahh yeah, the "dead zone" in the center. I thought of that the other day but forgot to mention it in the post. Thanks for reminding me of that little bit of not-so-fun coding, LOL

January 13, 2010
by Phrank916
Phrank916's Avatar

This is exactly what I want to do, but it's on a stupid Arduino.

http://www.youtube.com/watch?v=FKj9jJgj8Pc

So I guess I might get some ideas from looking at the servo.h library they reference. We'll see.

January 14, 2010
by Phrank916
Phrank916's Avatar

I'm up way later than I should be, but I just finished this little bit of code. It's really nothing, so trivial to most of you I'm sure, but I was extremely excited when the make went through and I turned on the MCU and it did what I wanted it to do!!

This is just a small part of what I want the final project to actually be, but it is a HUGE first step for me. This basically just reads a potentiometer and gives back an ADC reading between 0 and 1023. I print that to the LCD so I can turn the pot back and forth and watch the numbers go up and down :)

This code was mashed together from the tempsensor project and a little of my own..

#define F_CPU 14745600

#include <avr/io.h> 
#include <stdio.h>
#include <math.h>

#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"

uint16_t adc_read() {
  // read from ADC, waiting for conversion to finish
  // (assumes someone else asked for a conversion.)
  // wait for it to be cleared
  while(ADCSRA & (1<<ADSC)) {
    // do nothing... just hold your breath.
  }
  // bit is cleared, so we have a result.

  // read from the ADCL/ADCH registers, and combine the result
  uint16_t result = ADCL;
  uint16_t temp = ADCH;
  result = result + (temp<<8);

  // set ADSC bit to get the *next* conversion started
  ADCSRA |= (1<<ADSC);

  return result;
}
int main (void) 
{ 
  // Set ADC prescalar to 128 - 115KHz sample rate @ 14.7MHz 
   ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); 
   ADMUX |= (1 << REFS0); // Set ADC reference to AVCC 
   ADCSRA |= (1 << ADEN);  // Enable ADC 
   ADCSRA |= (1 << ADSC);  // Start A2D Conversions 
  // start up the LCD
  lcd_init();
  lcd_home();
  // holder variables for data
  uint16_t last_sample = 0;

  while(1) {
    last_sample = adc_read();

     // write message to LCD
    lcd_home();
    lcd_write_string(PSTR("ADC: "));
    lcd_write_int16(last_sample);
    lcd_write_string(PSTR(" of 1024   "));
    }

  return 0;
}
January 14, 2010
by Rick_S
Rick_S's Avatar

Great 1st step! Before long, you'll be challenging yourself to get an M&M! :D

January 14, 2010
by Phrank916
Phrank916's Avatar

So, I found an old PS2 controller which I started taking apart last night. The next R&D test I want to do is to make the ADC read the two pots of one of the analog joysticks and write that info on two separate lines of the LCD so I can again see the numbers changing in real-time.

I'm still a little unclear how to do that though. I know I need to use the ADMUX register to turn on a pin other than the default ADC0.

So here's what I THINK should happen. I need to create two functions for each channel and put in the ADMUX = 0 (question: would ADMUX &= ~(1<<ADC0) do the same thing?) in the first function and ADMUX |= (1<<ADC1) in the second function.

Then in the main loop I would call the first function and write to the LCD, then call the second function and write to line 2 of the LCD. My concern is the timing; I know it takes a number of clock cycles for each conversion, so would it be better to have an interrupt routine to write to the LCD before the next conversion? I assume since the ADC is multiplexed that I basically have to flip back and forth between the two channels doing a single conversion on each and grabbing the ADCL & ADCH bytes each time before starting another conversion. Clueless on how to make that work properly.

Ted

January 15, 2010
by Phrank916
Phrank916's Avatar

Latest updates to this project: I tore apart an old PS2 controller last night. This was fun because the only soldering iron I have right now is a cheap Weller battery powered model. It works OK but you have to hold down this little button to get it to start heating and it's a pain. Anyway, I harvested the two "rumble" motors, an LED, a small capacitor, the 9 strand connection wire, and the two analog joysticks. I actually left the joysticks soldered to the board right now because I'm thinking of keeping them in the controller housing for ergonomics.

A friend of mine gave me a little airplane servo similar to the one Mike & Humberto used on the servosquirter project and I decided to try hooking it up last night. I just took the servosquirter code, and commented out the "squirter/pump" lines so all I could really do was turn the servo side to side with the left and right bracket keys. It worked just fine!

Next step: I still need to get the joystick reading from both axes, then I should be able to get it's limits and calibrate with the servo through conversions in the code. Also gotta figure out some of the coding. I did work out some of the math last night and the formulas I'm gonna need in the code. Now just gotta get it all put together properly.

January 17, 2010
by pbfy0
pbfy0's Avatar

No idea if this'll work, I just copy&pasted (carelessly) from all the files that the example references.

January 20, 2010
by Phrank916
Phrank916's Avatar

I think I could steal some of the logic from that library, pbfy0. It's an Arduino library written for the "Wiring" language but most of the actual libraries are written in C or C++ because Wiring commands are essentially abstractions of C and C++ made to simplify Arduino programming. I only glanced at the library, but hopefully it doesn't refer to many other Wiring libraries.

January 22, 2010
by Phrank916
Phrank916's Avatar

SUCCESS!! Check this out:

YouTube

Let me know if you want the code, I'm tired of inserting 4 spaces all the way down. ;-)

Ted

January 22, 2010
by Rick_S
Rick_S's Avatar

Good job!! I've got to get a couple of servo's to play with. I could think of some interesting possibilities!!

Rick

January 22, 2010
by Phrank916
Phrank916's Avatar

Yeah, it's an awesome feeling knowing that I can now make my NerdKit do work! I'm trying to brainstorm and come up with something original. I don't want to just copy the M&M Maze.

January 22, 2010
by Phrank916
Phrank916's Avatar

Here's a link to the finished, but untested and non-debugged code if anyone is interested.

2pots2servos

I have no idea if this is going to work, so I hold NO RESPONSIBILITY for what you do to your MCU.

Ted

January 30, 2010
by Phrank916
Phrank916's Avatar

The project continues: I got the breakout boards for the joysticks this week. Soldered them up and then added some headers and made a makeshift connector to go into the breadboard. Video of my test:

video

Post a Reply

Please log in to post a reply.

Did you know that a piezoelectric buzzer can be used to play music with your microcontroller? Learn more...