learn.parallax.com
Published on learn.parallax.com (http://learn.parallax.com)

Home > Propeller C > Propeller C Tutorials > Simple Devices

Propeller C - Simple Devices

Propeller C - Simple Devices

A C-language tutorial for the 8-core Propeller microcontroller. It features the Propeller Activity Board. [1]Other Propeller boards will work in most cases; check each activity's circuit for notes.

What it's about

This set of lessons shows you how to interface a variety of devices to the multicore Propeller microcontroller. Each page includes a schematic, wiring diagram and test code with C libraries that make the programming simple.  You do not need to do these in order, just pick what interests you.  We will let you know if two lessons are meant to work together.

Keep checking back, because we will keep adding more.

Before you start

  • Set up the SimpleIDE software and your Propeller board [2]
  • Update your Learn Libraries [3]
  • Try Propeller C - Start Simple [4] if you are new to the Propeller microcontroller and/or C programming.
  • If you have never built circuits on a breadboard before, take a quick look at Breadboarding Basics [5].

After you finish

You will be ready to design your own projects that combine these devices.

Sense Distance with PING)))

The PING))) Ultrasonic Distance Sensor measures the round-trip echo time of ultrasonic sound to determine how far away an object is.  It can measure distances anywhere from 3 centimeters to 3 meters.  In addition to being a great distance sensor for robots, it’s also useful for detecting people passing through doorways, viewing art exhibits, approaching holiday props, and lots more.

Circuit

The PING))) Ultrasonic Distance Sensor only needs three connections to do its job: I/O pin, 5 V, and GND.

Parts

(1) PING))) Ultrasonic Distance Sensor (#28015) [6]
(1) 2 k-ohm resistor (red-black-red, #150-02020) [7]

  • Build the test circuit shown here. 

 

Note: if you are using a different Propeller board, build the equivalent circuit using the schematic.

Test

The test code displays the distance in centimeters to an object placed in front of the sensor.

  • Click SimpleIDE’s Open Project button.
  • Open Test Ping Distance from ... Documents\SimpleIDE\Learn\Examples\Devices\Sensor\Ping))) Ultrasonic Distance. 
  • Click the Run with Terminal button.
  • Place an object in front of the PING))) sensor and verify that the cmDist measurements change appropriately as you move the object closer and farther away.

How it Works

After the PING))) sensor receives a low-high-low Start pulse from the Propeller, it makes a brief ultrasonic chirping sound.  Since it’s ultrasonic, humans cannot hear it, but it’s loud enough that its own ultrasonic transducer can detect when the echo comes back. 

As soon as the PING))) sensor makes its chirp, it sets its output pin high.  When the echo comes back, it sets the pin low.  The Propeller measures how long the PING))) sensor holds this pin high, and that number is the round trip time for the sound to return.

The ping library has functions that take care of sending the start pulse and measuring the echo time pulse.  It also has functions that use the speed of sound in air to convert the echo time to a centimeter distance. 

The ping library was added to this project by clicking the Add Simple Library button, and navigating to …Documents\SimpleIDE\Learn\Simple Libraries\Sensor.  Then, select the libping folder, and click the Select Folder button.  After that, you’ll have access to the ping library’s functions.

In this program’s while(1) loop, int cmDist = ping_cm(15) makes a PING))) sensor connected to P15 report echo time.  It stores that time as a microsecond measurement and then uses the speed of sound in air to convert to a centimeter measurement.  int cmDist = ping_cm(15) copies the centimeter result the ping_cm function returns to a variable named cmDist.  After that, printf("cmDist = %d\n", cmDist) displays this value along with a newline character so that the next measurement appears on the next line in the SimpleIDE terminal.  After a 1/5 second delay made possible by pause(200), the loop repeats to display the next distance measurement.

/*
  Test Ping Distance.c
  Measure and display Ping))) Ultrasonic Distance Sensor distance measurements.
*/
#include "simpletools.h"
#include "ping.h"

int main()                                    // Main function
{
  while(1)                                    // Repeat indefinitely
  {
    int cmDist = ping_cm(15);                 // Get cm distance from Ping)))
    printf("cmDist = %d\n", cmDist);          // Display distance
    pause(200);                               // Wait 1/5 second
  }
}

Did You Know?

The speed of sound in air is 344.8 meters per second at room temperature (about 72 °F or 22.2 °C).  That’s c = 344.8 m/s, T = 72 ºF or 22.2 ºC. 

The distance (s) sound travels over a certain time is the product of the speed of sound and time.  That’s s = c × t.  If you are solving for round trip, the sound has to go twice as far, which takes twice as long, so divide your result by 2.  That’s s = c × t ÷ 2. There are 100 centimeters in 1 meter, and 1,000,000 microseconds in 1 second.  That’s 1 m = 100 cm and 1 s = 1,000,000 µs. 

So, if you have an echo time in microseconds and you want a distance measurement in centimeters it’s:

0.01724 happens to be really close to 1/58. The ping library uses s = t ÷ 58 because integer math saves memory and gets that job done more quickly than floating point.


Try this

Here is an example that uses the centimeter distance measurement to control the brightness of the LED connected to P27.  (You can use an LED on any available Propeller I/O pin. For a refresher on how brightness control works, see Set Volts. [8])

This particular example has a 25 cm range.  The closer the object gets, the dimmer the light gets.

  • Use the Save Project As button to save a copy of your project in …Documents\SimleIDE\My Projects.
  • Modify the main function as shown below.
  • Run the program and verify the output.

This program restricts the measurement to a maximum of 25 with if(cmDist > 25) cmDist = 25.  Then, cmDist is multiplied by 10, since the dac_ctr function expects a value from 0 to 255.  Finally, dac_ctr(27, 1, cmDist) takes the scaled-up cmDist value to control the LED with a range from 0 to 250 — almost the full range of LED brightness.  cmDist is re-initialized with the sensor measurement ping_cm(15) each time the loop repeats.

Your Turn

  • Modify your program to control the blinking rate of P26.
  • Modify your program to make the light get brighter when the object gets closer.  Hint: cmDist = 25 – cmDist; will invert your measurement, but you’ll have to do it before you multiply by 10.

SD Card Data

SD cards can give your Propeller microcontroller invention some extra gigabytes of memory to work with.  In this lesson, we’ll look at simple data storage and retrieval.  Later, we’ll look at audio and music applications and even writing code that can run from an SD card. 

Circuit

  • Plug a microSD card into the socket.

This lesson was written for the Propeller Activity Board.  It will also work with the Propeller Board of Education. If using a different Propeller development board, connect the card reader to the Propeller I/O pins listed below in How it Works, or update the global int variables at the beginning of SD Minimal.side to match your circuit.

Test Code

The SD Minimal.side project creates/opens a file on the SD card named test.txt for writing.  It then writes a string of characters into the file and closes it.  It then reopens it for reading, copies the contents to a character array, which gets displayed in the SimpleIDE Terminal.

  • Click SimpleIDE’s Open Project button.
  • Open SD Minimal from ... Documents\SimpleIDE\Learn\Examples\Devices\Memory. 
  • Click the Run with Terminal button.
  • Verify that it displays the “Testing 123...” message.

If the SimpleIDE Terminal just displays a blank screen, try SD with Tests.  It uses a more common procedure of checking for errors at each step in the file system mounting and file opening steps, and will display messages about certain problems encountered while executing the program. 

How it Works

The Circuit

See the metal stripes under the SD card?  Those are the electrical connections, called pads, that a device uses to communicate with the memory chip inside the card.

DO, CLK, DI, and CS are names for certain pads in the SD card.  Those pads get connected Propeller I/O pins to when you plug an SD card into a Propeller Activity Board socket.  The Propeller chip will send control signals to CLK, CS, and data to DI.  It will also receive data from DO.

The Code

First, four global variables are named and initialized for the microSD card pads, and the Propeller I/O pins they will be connected to through the board's card socket: int DO = 22, CLK = 23, DI = 24, CS = 25;

After a pause in the start of the main routine, these global variables are used by name in the function call sd_mount(DO, CLK, DI, CS).  This gives the SD driver library the information it needs to open the SD card and get its file system information. 

Once sd_mount opens the file system, you can then use functions from the stdio library (included by simpletools.h) to create and use files on the SD card.  The first such function call is FILE* fp = fopen(“test.txt”, “w”).

The fopen function creates a file (if it doesn’t already exist) and returns a value called a file pointer, here named fp.  fp will initially point to the start of the file. Later on, fp is used in operations for opening, writing to, reading from, and closing the file.

The fopen function takes two parameters.  First is a character array with the file name "test.txt" in our example.   Second is the mode, “w” in our example, which means the opened file can be written to.  (Other options include “r” for read and “a” for append.)

Characters can be written to the file with the fprintf function.  It is a lot like the familiar printf, except that it needs the file pointer to tell it where to put the values.  Here,  fprintf(fp, "Testing 123...\n") copies the characters in the string to successive locations in the test.text file.    When done,  fclose(fp) closes the file.

Next, the program sets up a character array with char s[15]; as a buffer to store data read from the SD card file.   Then, the file is opened for reading with fp = fopen(“test.txt”, “r”).  Then, fread(s, 1, 15, fp) tells the file system to copy data to the s character array, in 1 byte chunks, a total of 15 bytes, starting at the fp file pointer.  Since the file was just opened, fp points to the beginning of the file.  When done,  fclose(fp) closes the file again.

Finally, printf(“%s”, s) displays the values that fread placed in the s character array.  The %s format placeholder tells the printf function to send the values in the character array as a string of ASCII characters [9] to the SimpleIDE Terminal. One last printf("\n") moves the cursor down one line in the terminal.

/*
  SD Minimal.side
  Create test.txt, write characters in, read back out, display.
*/

#include "simpletools.h"

int DO = 22, CLK = 23, DI = 24, CS = 25;      // SD card pins on Propeller BOE

int main(void)                                // Main function
{
  pause(1000);                                // Delay for terminal

  sd_mount(DO, CLK, DI, CS);                  // Mount SD card

  FILE* fp = fopen("test.txt", "w");          // Open a file for writing
  fprintf(fp, "Testing 123...\n");            // Add contents to the file
  fclose(fp);                                 // Close the file
 
  char s[15];                                 // Buffer for characters.
  fp = fopen("test.txt", "r");                // Reopen file for reading.
  fread(s, 1, 15, fp);                        // Read 21 characters
  fclose(fp);                                 // Close the file.

  printf("First 15 chars in test.txt:\n");    // Display heading
  printf("%s", s);                            // Display characters
  printf("\n");                               // With a newline at the end.
}   

Did You Know?

stdio library — Check here for a complete list of stdio file input/ouput functions: http://en.wikipedia.org/wiki/C_file_input/output [10].

file pointer updates — After you opened the file, the first call to fprintf(fp, “Testing 123…\n”) updates fp so that it’s pointing at the byte that follows the newline (\n) character in test.txt.  If you call fprintf again, it will add more characters after “Testing 123…\n” because the fp file pointer was updated by the first call to fprintf.

Tiny Lib: uncheck it! — Projects using fprintf function calls with the SD card must have the Tiny Lib option un-checked.  When un-checked, your project uses the full stdio library, which can handle file I/O operations in addition to serial terminal I/O (and many other things).  Tiny Lib is a handy option to save space when you only need to use the serial terminal.  To find this checkbox, click the Show Project Manager icon in the lower-left corner of SimpleIDE, and then click the Linker tab.  This was done for you with the SD Minimal.side project. 


Try this

Just as you can use printf(“%d\n”, val) to display a value, so you also can use fprintf(fp, “%d\n” val) to store a value on the SD card.  Then, it is possible to retrieve the value with the function fscanf.  Let’s try it.  But be careful: fprintf fp, "%d\n", val) works fine, but fscanf also needs the address of the variable: as in fscanf(fp, "%d", &val).

  • Use the Save Project As button to save a copy of your project in …Documents\SimpleIDE\My Projects.
  • Modify the program as shown here.  Make sure to use the & sign in fscanf(fp, “%d”, &val). 
  • Run the program and verify the output.

Your Turn

  • Try recording and playing back twenty sensor measurements.  The measurements can be taken every half second for ten seconds. 

Good sensor choices include:

  • PING))) Ultrasonic distance sensor [11]
  • Phototransistor [12]
  • Potentiometer [13]

This type of project is called sensor datalogging, and has numerous applications in industry and the sciences.

Play WAV Files

Playing WAV files can enhance your project with music, a variety of tones, voice recordings, or even sound effects.  The multicore Propeller chip is particularly well suited to playing WAV files because it can use only a couple of its cores for reading the SD card and D/A conversion.  Meanwhile, other cores can adjust the playback volume, change files, or even execute code for sensors or displays. 

Setup

The Propeller Activity Board has built-in audio D/A amplifiers and a microSD card holder.  The Propeller microcontroller can fetch the audio data off the card, and use the D/A amplifiers to play back the sounds.

Parts

(1) formatted microSD card [14] (we used the preformatted card Parallax #32318; other SD cards might not provide the same sound quality)
(1) speaker or headphones with 3.5 mm plug [15] (we used the Veho speaker, Parallax #900-00018)

  • Insert a microSD card into the Propeller Activity Board’s microSD slot.
  • Plug in a speaker or headphones into the headphone jack. 

This lesson was written for the Propeller Activity Board.  It will also work with the Propeller Board of Education. If using a different Propeller development board, connect the card reader to the Propeller I/O pins listed below in How it Works, or update the int variables at the beginning of Test WAV Volume.c to match your circuit.

Audio Test

The wavplayer library is designed for 16-bit PCM, 32 kHz, mono WAV files.  A good source of free WAV files is www.freesound.org [16].  Audacity [17] is an excellent audio editor for converting other files to this format. 

  • Click SimpleIDE’s Open Project button.
  • Open Test WAV Volume from ...Documents\SimpleIDE\Learn\Examples\Devices\Audio. 

Before running this program, Let’s download a sample WAV file and load it into the SD card. (Hint: to keep from simply playing the WAV file with your browser, right-click the link and choose Save Link As... or Download Linked File.)

  • Download levels.wav [18]
  • Save it to … Documents\SimpleIDE\Learn\Examples\Devices\Audio
  • In SimpleIDE, click Program and select File to SD Card.  Click on levels.wav, and then click Open. It will take about 1 ½ minutes for the file to load. 

Now, let’s test the playback.  The Test WAV volume application plays at a volume of 6 (out of 10) for 5 seconds, then a volume of 4 for five more seconds, then a volume of 8 for 5 seconds, before stopping the playback.

  • Click the Load EEPROM & Run button.
  • Use a speaker or headphones to verify playback.

levels.wav started as a techno track downloaded from http://www.freesound.org/people/djgriffin/sounds/20715/ [19].  This track was opened with Audacity and changed from stereo to mono by clicking the Tracks menu and selecting Stereo Track to Mono.  Then, it was adjusted to repeat a second time by clicking Effect, selecting Repeat, and setting the Number of times to repeat to 1.  To finish, the Project Rate (Hz) was set to 32000.  Click File and Select Export, and make sure Save as type is set to WAV (Microsoft) signed 16 bit PCM and that the filename does not exceed 8 characters, no spaces.  When the Edit Metadata dialog appears, click the Clear button before clicking OK.  Then, your WAV file will be ready to load into your Propeller.

How it Works

This project includes simpletools.h and wavplayer.h.

First, four int variables are named and initialized for the microSD card's pads, and the Propeller I/O pins they connect to through the board's card socket: int DO = 22, CLK = 23, DI = 24, CS = 25;

Then, a call to sd_ mount accesses the SD card’s file system, using these variables by name: sd_mount(DO, CLK, DI, CS).   CLK, DI, CS);  (We could have just called sd_mount(22, 23, 24, 25), but named variables makes the code easier to understand and adapt if you are not using a Propeller Activity Board.)

After that, const char levels[] = {“levels.wav”} creates a character array with 10 slots, and fills them with the characters l e v e l s . w a v.  This array gets passed to the wav player with wav_play(levels). 

When the WAV player receives that string of characters, it searches for a file with that name in SD card’s root directory.  It then opens the file, reads the header information about data rate, bits per sample, and other details.  Then, it launches two more Propeller cores, or cogs. 

One cog fetches the D/A values from the WAV file and store them in an array. The second cog grabs values from that array, and use them to set the D/A converter output. 

That second cog updates its D/A output by reading the values in the array at a rate of 32,000 times per second, and updating the D/A converter's output with each D/A value from the WAV file. 

When the WAV file is playing, calls to wav_volume change the volume setting.  This function's vol parameter accepts integers in the range of 0 to 10.

/*
  Test WAV Volume.c

  Play back a .wav file and try a few different volume settings.   
 
  http://learn.parallax.com/propeller-c-simple-devices/play-wav-files
*/

#include "simpletools.h"
#include "wavplayer.h"

int main()                                    // Main function
{
  int DO = 22, CLK = 23, DI = 24, CS = 25;    // SD I/O pins
  sd_mount(DO, CLK, DI, CS);                  // Mount SD card
 
  const char levels[] = {"levels.wav"};       // Set up levels string
  wav_play(levels);                           // Pass to wav playwer
 
  wav_volume(6);                              // Adjust volume
  pause(5000);                                // Play for 5 s
  wav_volume(4);                              // Repeat twice more
  pause(5000);
  wav_volume(8);
  pause(5000);

  wav_stop();                                 // Stop playing
}

Did You Know?

wavplayer library — This useful collection of functions also includes wav_playing to find out if the WAV file is still playing, and wav_stop to stop playback. 

Switch tracks — You can call wav_play even if you are in the middle of playing back something else.  The library will automatically stop what it’s playing and then start playing the next one.

Thank you, sonicspot.com — The WAV player was developed with information about WAV files from this very helpful page: http://www.sonicspot.com/guide/wavefiles.html [20]


Try This - if you have a PING))) sensor

Since the WAV file is playing in other cogs, your code is free to work on other things, such as checking sensors.  Here is an example where the volume is set by a measurement from a PING))) Ultrasonic Distance Sensor.  We'll use the software's Add Simple Library button to add the ping library to our project and the #include “ping.h” directive to our code.

  • Use the circuit in Sense Distance with PING))) [21] to add the sensor to your board.
  • Use the Save Project As button to save a copy of your project in …Documents\SimpleIDE\My Projects.
  • Click the Add Simple Library Button.
  • Navigate to …Documents\SimpleIDE\Learn\Simple Libraries\Sensor\
  • Click libping and then click the Select button.
  • Modify the main function as shown below.
  • Run the program, and move your hand back and forth in front of the Ping))) sensor. When the cmDist value is small, the music is quiet, and when it’s large, the music is louder.

Your Turn

  • Use Audacity to make a couple of 16-bit PCM, 32 kHz, mono WAV file recordings of yourself saying different things.  Then, set up the pushbutton circuits from Check Pushbuttons [22] to select which phrase to say.

 

Tilt and Acceleration with the MX2125

The Memsic MX2125 two-axis accelerometer is great for measuring tilt, vibrations, rotation, and let’s not forget its namesake, acceleration.  A few MX2125 project ideas might include a tilt video game controller, tilt robot controller, robot hill climbing sensor, and radio vehicle acceleration, speed, and position data logger.

Circuit

The MX2125 sends two acceleration signals, one for its x-axis, and a separate one for its y-axis.  In this test, we’ll use P11 to monitor the y-axis signal and P10 to monitor the x-axis signal.

Parts

(1) Memsic2125 Accelerometer (#28017) [23]
(2) 220 ohm resistors (red-red-brown, #150-02210) [24]

  • Build the circuit shown here.

 

 

 

This lesson will work on any Propeller development board with a prototyping area.

 

Tilt Test

The Test 2125 Tilt application reports tilt in two directions: y-axis (left/right) and x-axis (toward/away from you).   

  • Click SimpleIDE’s Open Project button.
  • Open Test 2125 Tilt from ... Documents\SimpleIDE\Learn\Examples\Devices\Sensor\Accelerometer MX2125. 
  • Click the Run with Terminal button.
  • Hold the board level, and verify that both x and y tilts are close to zero.

  • Tilt the board to the right by about 45 degrees, and verify that the y-axis reports about 45. 
  • Try tilting to the left instead and check the sign of the angle measurement.

  • Tilt the board toward you by about 45 degrees, and verify that the x-axis reports about 45.
  • Tilt the board away from you, did the sign of the measurement change?

How it Works

The MX2125 sends out two streams of pulses, one for the X axis and one for the Y axis.  These high pulses last about 5000 µs (microseconds) when the board is held level. 

As the board is tilted, the high pulses will vary across a range of 3175 to 6125 µs.  Functions inside the mx2125 library scales these measurements to a range of  +/- 1250.  After that, it  converts the measurements to degrees with a maximum range of +/- 90. (The output range of your particular MX2125 unit may vary.)

You can add the mx2125 library to any project with the Add Simple Library button. Just click it,  navigate to …Documents\SimpleIDE\Learn\Simple Libraries\Sensor\libmx2125, and click OK.  This incorporates all of the library's files into your project and adds #include "mx2125.h" to your code. 

This library puts functions named mx_accel, mx_tilt, and mx_rotate at your service. 

Here, P10 is connected to the MX2125’s Xout pin, so  int x = mx_tilt(10) gets the x-axis tilt measurement and stores it in a variable named x. 

Similarly, int y = mx_tilt(11) gets the y-axis tilt and stores it in a variable named y.

In the example below, these measurements are taken and displayed with a printf statement, every 200 ms in an endless loop.

/*
  Test 2125 Tilt.c
 
  Measure tilt.  Assumes MX2125 is being held horizontally and then tilted.   
 
  learn.parallax.com/propeller-c-simple-devices/tilt-and-acceleration-mx2125
*/

#include "simpletools.h"                          // Include simpletools header
#include "mx2125.h"                               // Include mx2125 header

int main()                                        // Main function
{
  while(1)                                        // Repeat indefinitely
  {
    int x = mx_tilt(10);                          // X-axis tilt
    int y = mx_tilt(11);                          // Y-axis tilt
    printf("%ctilt x = %d, tilt y = %d, %c\n",    // Display tilts
            HOME,       x,           y, CLREOL);
    pause(200);                                   // 1/5th second before repeat
  }  
}

 


Did You Know?

The MX2125 has a tiny chamber inside that’s filled with nitrogen gas.  There’s a heating element in the middle, and temperature sensors around chamber's sides.

As you tilt the MX2125, the hotter gas rises.  The temperature sensor(s) closest to the hot gas detect these higher values.  Circuits inside the sensor use those temperature measurements to control the duration of the high output pulses that a microcontroller can read. 

Now does this work for measuring acceleration?  First, think about having a partially filled water bottle in a car seat.  As the car accelerates, the heavier water sloshes away from the direction the car is accelerating, pushing the lighter air forward.  The cooler nitrogen gas behaves like the water in your water bottle, sloshing away from the direction the sensor is accelerating.  Also like the water bottle, it displaces the hotter nitrogen gas toward the direction of acceleration.   The temperature sensors pick this changing temperature pattern, and update the output pulse widths accordingly.


Try This

You can hold your board vertically in front of you and turn it like it is a steering wheel.  The mx2125 library’s mx_rotate function will return the board's rotation angle in degrees, 0 to 359. 

  • Click SimpleIDE’s Open Project button.
  • Open Test 2125 Rotation from ... Documents\SimpleIDE\Learn\Examples\Devices\Sensor\Accelerometer MX2125. 
  • Click the Run with Terminal button.
  • Hold the board vertically and rotate it like it’s a steering wheel while you watch the SimpleIDE Terminal.

Your Turn

  • Try using the tilt angle returned by mx_rotate to control something.  It could be speaker tone, LED brightness, servo position, or even the position of a character in the SimpleIDE terminal. 

Hint: for character position, you’ll need to use some math on the x and y values to scale them into a range 0 to 20. Then, use printf(“%c%c%c*”, CRSRXY, x, y) to place an asterisk in the SimpleIDE Terminal, or printf(“%c%c%c ”, CRSRXY, xOld, yOld) to blot out the previously positioned asterisk with a space.

Joystick

The Parallax 2-Axis Joystick can be used for a wide variety of projects like wheeled robots, video games, or anything requiring user input. Like most joysticks, the Parallax 2-Axis Joystick uses two variable resistors (called potentiometers) to read the user’s input. Remember reading a potentiometer’s value back in Measure Volts [13]? Reading a joystick’s position is a matter of measuring two potentiometer voltages. One reports the left/right position and the other reports the up/down position. 

Circuit

The Parallax joystick contains two 10 kΩ potentiometers, one for each axis. We’ll read the value from the potentiometer using an analog to digital converter, or ADC, just like in Measure Volts. For our joystick, we’ll use one of the ADC’s inputs for each axis. In this case, up/down (U/D) is connected to channel 2 and left/right (L/R) is connected to channel 3. The potentiometer also needs to be powered, so we’ll attach the potentiometer’s pins labeled L/R+ and U/D+ to 5 V, and the GND pin to ground. Note that there are two of some of these pins—it doesn’t matter which one you use, they are electrically the same.

Parts

(1) Parallax 2-Axis Joystick (#27800) [25]

  • Build the circuit as shown below.

Note: This lesson is designed for the Propeller Activity Board.  It is not compatible with the Propeller Board of Education, which uses a different A/D converter.

 

Test Code

This test code will read both axes of the joystick and display voltage values for each. Since the potentiometer is connected to 5 V, the middle of the joystick (where it goes when you release it) will display 2.5 V on both axes. You may notice slight deviations from 2.5 V; this is explained more in the Did You Know? section.

  • If you haven't already installed the latest USB driver, SimpleIDE, or Learn folder, go to Propeller C - Set up SimpleIDE [2] and Propeller C - Start Simple [4]
  • Download the Joystick_adc project archive [26]
  • Unzip the archive and run joystick_adc.side. 
  • Click the Run with Terminal button.
  • Verify that you get voltage readings like those shown below.
  • Try moving the joystick around. Do the voltages vary from 0 to 5 V, as you’d expect? What happens at the corners?

How it Works

The code includes the adcDCpropab library with the command #include "adcDCpropab.h". This library is designed for measuring voltages using the A/D converter on the Propeller Activity Board.  The function adc_init gets called first, to tell it which Propeller I/O pins are connected to the A/D converter's /CS, SCL, DO and DI pins.  Together these pins are called an SPI bus, over which the Propeller communicates with many peripheral devices. You will find the SPI pin numbers next to the A/D converter chip, which is right below the GND sockets on your board. 

After that function, float x, y declares two floating point variables for storing measurements.  Inside the while(1) loop, udV = adc_volts(2) stores the voltage at A/D2 into the udV variable, and lrV = adc_volts(3) does the same for A/D3.  A couple of printf calls display the two voltage values, followed by a 1/10 second pause before the loop repeats.

/*
  Joystick.c
  Version compatible with SimpleIDE 0.9.28 (Win) or 0.9.26 (Mac)
  Simple Propeller P8X32A Propeller C demo with the Parallax 2-axis Joystick

 
*/
#include "adcDCpropab.h"                            // Include adcDCpropab
#include "simpletools.h"                            // Include simpletools


int main()                                          // Main function
{
  pause(1000);                                      // Wait 1 s for Terminal app
  adc_init(21, 20, 19, 18);                         // CS=21, SCL=20, DO=19, DI=18

  float lrV, udV;                                   // Voltage variables

  while(1)                                          // Loop repeats indefinitely
  {
    udV = adc_volts(2);                             // Check A/D 2                
    lrV = adc_volts(3);                             // Check A/D 3
   
    putchar(HOME);                                  // Cursor -> top-left "home"
    printf("Up/Down = %.2f V %c\n", udV, CLREOL);   // Display voltage
    printf("Left/Right = %.2f V %c\n", lrV, CLREOL);// Display voltage

    pause(100);                                     // Wait 1/10 s
  }  
}

Did You Know?

  • A/D Converter Range: The Propeller Activity Board’s A/D converter sends numbers ranging from 0 to 4095, which represent values that range from 0 to 4.99878 V.  If you supply it with 5 V, it’ll still display 4095, which is the highest it can go.  These raw A/D values represent the number of 4095ths of 5 V.
  • Output and Tolerance: You may have noticed that when you let up on the joystick the voltages are not exactly 2.5 V. For example, our joystick rests around 2.49 V in the Up/Down axis (y axis) and 2.53 V in the Left/Right axis (x axis). This is due to the way potentiometers are manufactured. Like all electronic devices,  potentiometers have tolerances, meaning the permissible range of variation in the output (for example, ±10%). For any two devices, the tolerances often do not fall in the same direction, as is the case with the potentiometers in this particular joystick. Many video game controllers allow a “dead zone” in the middle of the joystick to correct for this effect.

Try This

Instead of displaying the voltage values from the joystick, let’s display a range representing the joystick's position. To do this, we’ll need to scale voltages going from 0 to 5 V into values from -100 to 100.

  • Use the Save Project As button to save a copy of your project in …Documents\SimpleIDE\My Projects.
  • Modify the main function as shown below.

  • Run the program and verify that you see values between -100 and 100 instead of voltages for each axis.

Your Turn

You may want to drive a servo with your joystick. Perhaps you want your servo to start at 90 degrees and move ±60 degrees from there. Write some code to do this scaling, and output the result for each axis on the terminal.

  • This is a simple application of y=mx + b. In the example above, m was 40 and b was -2.5/40. See if you can figure out the new equation for the servo application.
  • Try changing the program in Try This to display 0 to 100% instead of -100 to 100.

Hint: to display the “%” character in the serial terminal, we need to type two of them in the printf command. This is because % acts as a special operator in printf commands so it is necessary to have two % characters tell printf to display a literal “%.” 

Standard Servo

A hobby servo is a small device that controls the position of flaps, rudders, and steering in many radio-controlled toy planes, boats, and cars. The Parallax Standard Servo is a hobby servo, and it’s also a useful in many robotics and animatronics projects.  Since it can both move to and hold a position, it is ideal for tasks like rotating a distance sensor or controlling the fingers in a robotic hand. 

This tutorial will show you how to make a servo hold three different positions, and then guides you through creating smooth, continuous motion through small, evenly-timed changes in position.

Setup

Parts

(1) Parallax Standard Servo (#900-00005) [27]
(1) 3” Jumper Wire (#800-00016) [28]
(1) Power supply. Options include:

  • 4-cell AA battery pack (#700-00038) [29]with 1.5 V batteries
  • 5-cell AA battery pack (#753-00007) [30]with 1.2 or 1.5 V batteries
  • 7.5 V 1 A Power Supply (#750-00009) [31]
  • Li-ion Boe-Bot Power Pack-Charger (#28988) [32] with 7.5 V Li-Ion batteries

Supply Settings

A servo can draw more current than a USB port can supply, so you’ll need to plug an external power supply into the Activity Board’s 6 to 9 V power jack.  Since the Parallax Standard Servo is rated for a 4 to 6 V supply, you may also need to move the Activity Board’s servo port power jumper settings to regulated 5V.

There are three pins to the immediate left of each pair of servo ports on the Propeller Activity Board. A small metal and plastic jumper can connect the middle pin to either the top or the bottom power pin. This is the power-select jumper for that pair of servo ports.  When the jumper is over the bottom and middle pins, the pair ports' V+ pins receive 5 VDC through the board's voltage regulator. When the jumper is over the middle and top pins, the ports'  V+ pins receive unregulated voltage directly from the power supply connected to the board. 

  • If your power supply is 6 V or less, set the power-select jumper for the P16 servo port to 5V - this is safe for all power options listed above.
  • If you are using a 4-cell battery pack (or are sure your power supply is 6 V or less) you may set the P16 servo port jumper to VIN - this is safe for the 4-cell battery pack.

 

Servo Angle Marker

It helps to make some sort of angle marker on the turning part of the servo (called its control horn) to know what position it is in. A jumper wire is handy for this.

  • Find the middle of the servo’s range by gently twisting the horn right and left to find the mechanical stops, then positioning it in the middle of its range.
  • Twist the wire through the top two holes at the center of its range to mark the "middle" position. When finished, it will most likely look something like the figure below.

Circuit

  • Build the circuit as shown below.

 

  • Plug in your external supply.
  • When you’re done, make sure your setup looks something like the one below.

If you haven't already installed the latest USB driver, SimpleIDE, or Learn folder, go to Propeller C - Set up SimpleIDE [2] and Propeller C - Start Simple [4].

 

Test Code

The servo test code will move the servo to the three positions shown below (0°, 90°, and 180° ) with three seconds to move between and hold each position.  While the program is running, the servo will resist any attempt to move it out of position. When the program finishes, the servo will stop resisting.

  • Click SimpleIDE’s Open Project button.
  • Click the Load RAM & Run button.
  • Verify the servo holds the 0° position, then 90° position, and then the 180° position, each for about 3 seconds.
  • Try modifying the program to make the servo hold a 45° angle and a 135° angle. Verify it works as you would expect.

 

How it Works

The servo_angle() function call takes two parameters: the pin the servo is connected to and the servo angle in tenths of a degree. For example, to make the servo connected to P16 turn to 90 degrees, the program uses servo_angle(16, 900).  Keep in mind servo_angle() does not wait for the servo to get into position—it is necessary to include a pause for the servo to reach the desired position before setting a new angle. 

/*
  Standard Servo Position.c
 
  Moves servo to 0, 90 and 180 degrees.  Holds each position for 2 s.
  Connect servo to P16 port on Propeller ActivityBoard.
*/

#include "simpletools.h"                      // Include simpletools header
#include "servo.h"                            // Include servo header

int main()                                    // main function
{
  servo_angle(16, 0);                         // P16 servo to 0 degrees
  pause(3000);                                // ...for 3 seconds
  servo_angle(16, 900);                       // P16 servo to 90 degrees
  pause(3000);                                // ...for 3 seconds
  servo_angle(16, 1800);                      // P16 servo to 180 degrees
  pause(3000);                                // ...for 3 seconds
  servo_stop();                               // Stop servo process
}

Did You Know?

Satellite dish image source: http://deepspace.jpl.nasa.gov/dsn/gallery/goldstone6.html [33]

Servos aren’t just for hobbies. Much larger servos are used to precisely aim the position of huge satellite dishes towards extraterrestrial targets, like those in the Deep Space Network (above, left).  Additionally, most robotic hands (like the one shown above right) are actuated by servos. Depending on how many independent degrees of freedom the hand has, it could use dozens of servos! The hand above is actuated using five standard servos.


Try this

Let’s use a feature called ramping to make the servo move to new positions gradually. Ramping  “cushions” or “smooths-out” the servo’s responses to large or sudden changes in sensor measurements by limiting how much it can change position over a given amount of time. This servo control library's servo_setramp() function takes two parameters: the servo’s pin, and the speed at which the servo will change in tenths of a degree per 50th of a second.

Once servo_setramp() is called, every servo_angle() call that follows it will move at the rate set by servo_setramp.  Without this command, the servo will always move to new positions at its maximum speed. In this example, the servo will move to its first two positions at full speed just like it did in the program above. Then servo_setramp(12, 8) will slow it down to .8° per 50th of a second as it moves to the last two positions.

  • Use the Save Project As button to save a copy of your project in …Documents\SimpleIDE\My Projects.
  • Modify the main function as shown below.

  • Run the program and watch the servo as it turns rapidly to the first two positions then gradually to the next two.

In this example, the servo moved from 180 degrees back to 90 degrees more gradually because of servo_setramp(), but it still made it there and paused. What do you think would happen if you changed the rate to .5 degrees per 50th of a second? Would the servo make it to 180 degrees before turning back? Try it!

 

Your Turn

Imagine you’re the engineer in charge of animatronic devices at an amusement park.  Let’s say one exhibit contains two servos for its face, and needs to display five expressions, one each thirty seconds. One way to do this would be by storing these expressions in two arrays (one for each servo).

If you haven’t worked with array variables before, check out the Array Variables [34] tutorial. Then, try the Index Array Variables [35] tutorial and pay close attention to how the code loops through an array using a for loop and then uses printf() to display the values. Instead of displaying the values in the arrays with printf(), you can send them to a servo with servo_angle().

Here is some code where we give printf() p[i] as an input. Think about how you would change printf() to servo_angle() so that it uses the indexed array value p[1]  as the angle, and keep in mind you’ll need to increase the pause.

 int p[] = {100, 200, 300, 500, 700, 1100};          // Initialize the array
 for(int i = 0; i < 6; i++)                          // Count i from 0 to 5
 {
   pause(500);                                       // 1/2 second pause
   printf("p[%d] = %d\n", i, p[i]);                  // Display array element & value
 }

Add a P17 servo to your code. You can still test this code if you only have one servo. Run the code with the servo connected to P16 first, then turn off your board and switch the connection to P17. Run the test again to verify that if you had two servos, they would be working correctly and independently.

SHOP IN THE PARALLAX STORE ►

Terms of Use ♦ Feedback: learn@parallax.com ♦ Copyright©Parallax Inc. 2012 (unless otherwise noted)


Source URL: http://learn.parallax.com/propeller-c-simple-devices

Links:
[1] http://learn.parallax.com/node/653
[2] http://learn.parallax.com/node/640
[3] http://learn.parallax.com/node/658
[4] http://learn.parallax.com/node/617
[5] http://learn.parallax.com/node/667
[6] http://www.parallax.com/tabid/768/ProductID/92/Default.aspx
[7] http://www.parallax.com/tabid/768/ProductID/218/Default.aspx
[8] http://learn.parallax.com/node/648
[9] http://learn.parallax.com/node/538
[10] http://en.wikipedia.org/wiki/C_file_input/output
[11] http://learn.parallax.com/node/639
[12] http://learn.parallax.com/node/649
[13] http://learn.parallax.com/node/647
[14] http://www.parallax.com/tabid/768/ProductID/852/Default.aspx
[15] http://www.parallax.com/tabid/768/ProductID/803/Default.aspx
[16] http://www.freesound.org
[17] http://audacity.sourceforge.net/
[18] http://learn.parallax.com/sites/default/files/content/propeller-c-tutorials/simple-devices/Play WAV/levels.wav
[19] http://www.freesound.org/people/djgriffin/sounds/20715/
[20] http://www.sonicspot.com/guide/wavefiles.html
[21] http://learn.parallax.com/node/659
[22] http://learn.parallax.com/node/635
[23] http://www.parallax.com/tabid/768/ProductID/93/Default.aspx
[24] http://www.parallax.com/tabid/768/ProductID/220/Default.aspx
[25] http://www.parallax.com/tabid/768/productid/581/default.aspx
[26] http://learn.parallax.com/sites/default/files/content/propeller-c-tutorials/simple-devices/Joystick/joystick_adc-0-9-28.zip.zip
[27] http://www.parallax.com/tabid/768/ProductID/101/Default.aspx
[28] http://www.parallax.com/tabid/768/ProductID/195/Default.aspx
[29] http://www.parallax.com/tabid/768/ProductID/275/Default.aspx
[30] http://www.parallax.com/tabid/768/ProductID/867/Default.aspx
[31] http://www.parallax.com/tabid/768/ProductID/73/Default.aspx
[32] http://www.parallax.com/tabid/768/ProductID/782/Default.aspx
[33] http://deepspace.jpl.nasa.gov/dsn/gallery/goldstone6.html
[34] http://learn.parallax.com/node/620
[35] http://learn.parallax.com/node/630