Saturday

Asynchronous WAV/PCM: Arduino Audio Library Update:

 This library allows asynchronous playback of WAV files using only an Arduino, SD module, and a speaker.

 A little while ago, I decided to create a library for simple wav file playback using an Arduino, since I couldn't find any that fit my needs

Logical Functionality: 

I posted two previous versions of this libary, one that used a buffer, and one that used interrupts to load the data. Each had its tradeoffs, and neither were perfect. The interrupt based version had noticeable sound quality issues, and the buffering version could not be easily stopped during playback, or the volume adjusted, etc.
 The problem as I understand it, is that a read from the SD card will actually read 512 bytes at a time, so the buffering interrupt would not always complete before the music interrupt was set to trigger next. Since only 1 interrupt will trigger at a time, timing was an issue and so created other issues.

Searching through the datasheet for some functionality that would allow me to do what I wanted, I stumbled across mention of 'nested' interrupts. It took a little bit of time to figure out exactly how to use them in this application, but here is a brief overview of how the timer and interrupts work together:

OVF: This is an interrupt overflow vector that is triggered everytime the timer 'overflows'. (every cycle) Here, it reads a byte from the buffer into OCR1A, and therefore changes the pwm duty every cycle (@16khz)

COMPB: This is an interrupt compare match vector that is triggered when compare match is made during the timing cycle (TCNT1 == ICR1). This interrupt vector is used to read data into the buffers. Can be interrupted by other interrupts via 'nested interrupts'.

a: Interrupt vectors enabled: OVF, COMPB
b: When COMPB is triggered, it disables itself, but leaves OVF enabled. Global interrupts are automatically disabled while an interrupt completes. To enable nested interrupts, global interrupts are enabled manually before reading from the SD card.
c: If ready to buffer data, it begins (OVF can now interrupt COMPB while it bufferrs data)
d: COMPB completes, and re-enables itself to trigger again while it waits to buffer more data

Thanks to nested interrupts, I finally have what I wanted, with the basic functionality one would expect. I think the code can still use a bit of tweaking though, since I haven't fully tested its limits.

Updated Features:
- Sound Quality/Distortion issues have been resolved
- Uses a single timer (timer1)
- Asynchronous (interrupt driven) playback and buffering allows other code to run while music plays 

iTunes Conversion: 
a: Click Edit > Preferences > Import Settings
b: Change the dropdown to WAV Encoder and Setting: Custom > 16.000kHz, 8-bit, Mono

c: Right click any file in iTunes, and select "Create WAV Version"

d: Copy file to SD card using computer

Function Usage:
tmrpcm.play("filename"); //plays a file
tmrpcm.speakerPin = 11; // set to 11 for Mega, 9 for Uno, Nano, etc
tmrpcm.volume(1); //raises or lowers the volume: 1 or -1
tmrpcm.disable(); //disables the timer on output pin and stops the music
tmrpcm.stopPlayback(); //stops the music, but leaves the timer running

Individual Files:

Library Package:
TMRpcm.zip (OLD)
(now hosted on GitHub here)

Updated: 
Added Functionality:
Automatic detection of sample rate (8000 - 22000Hz)
WAV format verification
Memory buffer 300 bytes
Phase/Frequency-Correct and Fast PWM modes
 
Added functions: 
tmrpcm.isPlaying();  //returns 1 if music playing, 0 if not
tmrpcm.pause();  //pauses/unpauses playback
tmrpcm.pwmMode = 1; //set to 1 for phase/frequency correct mode, 0 for fast pwm 
tmrpcm.volume(0); //CHANGED from prev version, now uses either a 1(up) or 0(down)

Tested with: Arduino Nano/328 and Mega2560 
TMRpcm.zip  (OLD)

(Current version on GitHub here)

Monday

WAV/PCM Library Update:

 After reading into the capabilities of the Arduino timers, it seemed possible to generate an audio signal from PCM/WAV data using a single timer. Reading through the documentation, and looking at examples like the Timer1/Timer3 libraries, I found that I could use OCRnA to control duty cycle, ICRn and prescale for frequency, and use an overflow interrupt to update the value of OCRnA according to the defined SAMPLE_RATE, all with one timer.

How it works:

16-bit timer 1 is used for compatibility with different Arduino boards, but 16-bit Timers 3, 4, or 5 could be used on a Mega also.

The timer is set to Phase and Frequency Correct Mode, and set to run at a defined sample rate. The settings for prescale (TCCR1B) and input capture (ICR1) are what determines the frequency of the PWM signal when timer 1 is used, and OCR1A controls the duty cycle.

 An interrupt is attached to trigger every time the timer hits bottom. (Generally 16000 c/s) At this rate, an interrupt is generated 16000 times per second, and a new value is set for the duty cycle(OCR1A), then a new value is buffered for the next cycle.

In short, a signal is generated at 16000hz. The length of time each cycle stays turned on is determined by the value read in from the WAV/PCM file, which is updated every cycle.

No buffering: I am not sure of read speeds for SD cards, but testing indicates slightly higher sample rates can be achieved with no modifications. The SD library appears to default to SPI_HALF_SPEED, but will leave that inquiry for another day...

Whats new:

a: This version is completely controlled by interrupts, allowing other functions to run while music is playing. 
b: There is no longer a requirement for a large memory buffer, bytes are loaded as required
c: Added function to raise/lower volume: tmrpcm.volume(1);
d: Due to interrupt-driven playback, ability to stop/start music at will is added 

Data Format: unsigned 8-bit pcm, 16khz sample rate

iTunes Conversion: 
a: Click Edit > Preferences > Import Settings
b: Change the dropdown to WAV Encoder and Setting: Custom > 16.000kHz, 8-bit, Mono

c: Right click any file in iTunes, and select "Create WAV Version"

d: Copy file to SD card using computer

Function Usage:

 TMRpcm tmrpcm;              //Declare new object
 tmrpcm.speakerPin = 11;    //set to 11 for Arduino Mega, 9 for Uno, Duemilanove, etc
 tmrpcm.volume(1);             // 1 to raise volume, 0 to lower volume
 tmrpcm.play("filename");     // plays an unsigned 8-bit wav file from SD card
 tmrpcm.stopPlayback();     //stops playback
 tmrpcm.playing();               //returns true during playback, false otherwise

Updated Files / Source: 

Notice: This version has audio quality issues. See newer blog post for updated version

Source:
Example: music.ino  //Plays music while blinking a LED via the loop function 

Library Package:
TMRpcm.zip (Current version here)

Tuesday


Arduino WAV Playback Direct from SD Card 

*TMRpcm Library beta released*

The Problem: 

I wanted to be able to play a variety of sound clips using the Arduino, but could only find examples or libraries using program memory or other such methods. There are music shields you can get, but no examples for playing raw files from an SD card that I could find.

The Solution - Build a Library:
  
My library is directly based on the code shown at arduino.cc/playground/Code/PCMAudio as well as the library shown at: hlt.media.mit.edu/?p=1963, both of which use PROGMEM.
This is also the first library I have written, so there may be a few items slightly off, especially at this point in developing it.

First off, I had no idea how to make this work, but since it could work from progmem, why not from an SD card? Some sort of buffering would be needed for sure but how much, how to implement, etc. were some of the issues that had to be figured out.

Since I had no idea what I was doing exactly or how I was going to do it, I attempted to convert the files/data from the above links into char or byte format and saving it directly to a file on the SD card with no spaces, commas, etc. and playing it using the same method. It actually worked!

Once I proved the concept, then it was a matter of finding the best/simplest way to format the data for playback. Checking into the format of WAV files, I realized that they can be saved into a format that I can read directly using an Arduino with an SD card. There is a small header at the beginning of the file, but then it is basically raw data. The data can be saved in an 8-bit format (0-255), which can be read into the Arduino, and written directly to the registers with no modification.

The next problem is that I have never written a library, and Arduino programming is somewhat new to me, although I have dabbled in various programming languages for "fun" over the years. Following the tutorials found online, I was able to turn my sketch into a library.

For me, the easiest method was to use iTunes to convert the wav files, but any PCM file in the correct format will work:


Click Edit > Preferences > Import Settings

Then change the dropdown to WAV Encoder and Setting: Custom > 16.000kHz, 8-bit, Mono

Now you can just right click any file in iTunes, and select Create WAV Version

Then just copy the file(s) to an SD card attached to an Arduino, and check out the library below, with included example sketch.


How it works:

Both the above example and library this was based on use PROGMEM to store the variables which drive the PCM signal. Since we are reading WAV files directly from SD, we can save as many as the SD card will allow, with general disregard for file size.

The library uses timers and interrupts to create a signal that runs at 16000 cycles/second. The signal is controlled by the variables we read in from a file. The file is read into a small buffer, and playback is started. While interrupts control the playback, the second buffer starts filling up with data, using the spare cpu cycles between interrupts, and resumes playback once the first buffer is 'emptied'. Then the first buffer starts loading data again, while the second is 'emptied' and so on. This allows a continuous stream of data to be available for playback. Testing seems to indicate a minmum requirement for about 400 bytes of total memory for a steady stream and/or reasonable sound quality. (soundBuff = 200)

How to load data: In order to load the needed data onto an SD card, the wave file must be in the correct format, or converted using iTunes and the instructions above. Basically, this can be done using any computer with an SD slot, using any method that outputs wav files in the correct format.

Conclusion: This is totally possible, and it now works! The sound quality is low, but for simple sound clips, this is reasonable.

Example:

File(s) are placed onto the root of the SD card, then the following sketch is run:

 _________________________________________________________________

#include <SD.h>                      // need to include the SD library
#define SD_ChipSelectPin 53  //example uses hardware SS pin 53 on Mega2560
#include <TMRpcm.h>           //  also need to include this library...

TMRpcm tmrpcm;   // create an object (tmrpcm) for use in this sketch

void setup(){
 

tmrpcm.speakerPin = 10;
tmrpcm.soundBuff = 500; //uses 1KB memory. Min setting is about 200 (400 bytes)
 
pinMode(10,OUTPUT); //speaker pin
Serial.begin(115200);
  if (!SD.begin(SD_ChipSelectPin)) {  //see if card present and initialized:
    Serial.println("SD fail");  return;   // don't do anything more if not
  }else{   Serial.println("SD ok");   }

  tmrpcm.play("music"); //file "temple" plays when arduino powers up, or reset
}

void loop(){
  
  if (Serial.available() ){
    if (Serial.read() == 'C'){ 
      tmrpcm.play("music"); //sending a C to serial port starts playback
    }
  }
}
_________________________________________________________________

Modify the filenames for tmrpcm.play() to match your file.

Function Usage:

play("myFile");
stopPlayback();

Files/Source:

Developed using Arduino IDE 1.0.1
This is more or less just proof-of-concept currently, and will only work on Arduino Megas currently.


Source Code (OLD):
   TMRpcm.h
   Example: music.ino

Original Library Package (OLD):
   TMRpcm.zip

Current version on GitHub (download)
See the Wiki for updated usage and info



Wednesday

Visual Tracking Continued...  Look, No Tape!

My view of the JunkBot from my PC while I direct its movements with my mouse



Physical:

Parts/Stuff:

iPod with EpocCam (or actual webcam) sends data vi WiFi to
Computer running Processing sketch sends data via USB/Serial connection to
Arduino Nano is attached to
315Mhz RF Transmitter sends data to
JunkBot (detailed in previous posts)

This sketch should work anywhere there is consistent lighting and no movement other than that of the object being tracked. (indoors) Using the current method of a single screenshot compared against video input, this will not work well or at all if there are other moving objects or large changes in lighting.



Logical:

The sketch has been updated since the video above was taken. It now uses a single display window, and the views are toggled using keys 1,2 and 3.

Processing Sketch: here

The processing sketch uses the OpenCV library ( http://ubaa.net/shared/processing/opencv/ )to track the position and movements of the JunkBot. The iPod is using webcam type software to transmit the video over Wifi, but any webcam supported by the CV library will work. 
The sketch simply compares a screenshot taken without the bot in view against the current video capture, and determines the position of the bot. From there the information is sent to an Arduino based RF transmitter listed below. (2 bytes, speed for motors 1 and 2)
Movement is currently a bit 'swervy' compared to the physical line following version from a previous post, due to the delays involved in processing the video data and relaying commands. I am fairly sure this can be improved with better code for determining required movements.

Controls:

'4' key: Grab a screenshot and save it to file as specified.
'3' key: Load image file saved using '4' into memory and display difference image
'2' key: Display screenshot file only
'1' key: Display main view including lines, tracking box, etc.

'S' key: Begin. On first start only, signals will be sent increasing motor speed until movement is detected. This is used as the base speed. Once ranging is complete, commands will be sent to move to the indicated position at this speed.
'A' key: Stop
'+' key: Faster
'-' key: Slower

Mouse: Click and drag adjusts the Threshold (See OpenCV reference), Click/NoDrag sets a new position.

Transmitter: here
The transmitter uses the VirtualWire library and a 315Mhz transmitter to relay commands to the JunkBot. Commands are formatted to work with the standard JunkBot code listed below. The code simply waits for 2 bytes of serial data from the Processing sketch, and relays that information to the JunkBot. If no additional commands are received within 1/4 second, the commands are sent again to help ensure reception.


Current JunkBot_SD: here

JunkBot_SD code is as described in previous post. I might post a simple version just for visual tracking since this one is pretty rough and bloated.

Monday

Visual Tracking with Arduino,Processing, and an iPod


A first attempt at tracking movement:



Starting and stopping of the JunkBot while it moves in a circle.

Using OpenCV(ComputerVision) Processing library to receive data wirelessly from an iPod video camera, then process it and send controlling data to an Arduino. This Arduino relays the information via 315Mhz RF link to the JunkBot. In this demo, the JunkBot is told to hang around the center point of the circle.

As usual, the JunkBot does not analyze the incoming commands. Like any good robot, it just does what it is told... More to come.



Sunday


JunkBot Line Follower 
Physical: 

The JunkBot has been slightly updated with a larger platform, and I replaced the h-bridge with a motor driver module. This was done for simplicity, size, and just to test it out. The code did not have to change since they are driven in the same manner. 

The line following 'sensor' uses a laser and two IR sensors to detect the line. Variable resistors are used to set the sensitivity of the sensors. I chose to use a laser since I had one on hand and it is capable of overwhelming ambient light sources. My initial design used an LED, which worked almost as well. I removed the lense from the laser, making the width of the beam wider than the strip of tape. The IR detectors are mounted just below the laser, and the beam passes between them and reflects off the floor. The detectors are shielded with black electrical tape.

 














  




Logical:

Fairly simple code, the value of each IR detector is read into an analog input, and motor speed is tied directly to these values. When line is between the detectors, slight adjustments are made. When line is out of these boundaries, more aggressive adjustments are made.

Written using the Arduino IDE, running on Arduino Nano/ATmega328

JunkBotX_SD_LF preliminary code here (Current code for testing, all other functions disabled)

Functionality:

Put together mostly out of curiosity, it follows lines in a fairly smooth way without diverting from the defined course. Could be fine tuned for smoother or more precise adjustments if required. This may be useful in repositioning or determining location based on visible markings.



Arduino / XBox V1 RF(Wireless) Controller Hack:














                                                 




Physical:

The above pictures show the process of installing an Arduino Nano into a generic wireless Xbox V1 controller and wiring it up. I removed the vibrating motors, chopped the circuit board, and added my own transmitter (visible on top-left of controller). I also chopped a hole for USB connection and transmitter wires which will be shortened. (315Mhz RF module using VirtualWire)

If you look close you will see that the wiring could have been laid out much better and arranged in more of a logical way. I didn't plan on using all the buttons and d-pad, but once I got started, I couldn't leave all those unused pins and buttons. It was also bit of a rush job as usual.

The joysticks work by using 2 potentiometers each as shown in the above pics (Orange), and the triggers use just one. All I had to do was scratch out the connections on the circuit board and wire up my own. I also chopped the circuit board in half to make more room for the Arduino. I currently have both joysticks, the d-pad, triggers and A-B-X-Y buttons all functioning. (uses 6 analog and 8 digital pins). Built in LED indicator is wired to pin 13.

I am not posting a schematic for this since it is pretty straight-forward, but here are some basic steps:

1. First off, the 'outputs' on the controller itself are just potentiometers and buttons. They get wired to the Arduino in the same way as any potentiometer or button.
2. Connect the center of each pot to an analog input
3. Connect each button to a digital input.
4. Leave all ground connections in place
5. Scratch out + connections and wire your own to 5v on Arduino. Use resistors built into controller where possible, otherwise include where required.
6. Adjust input pins in source code as necessary.

The only complicated part is the number of wires to connect and fit in there.

Logical:

The controller starts by determining the zero-point or center area of the joysticks. Any slight movements in this area will be equal to zero movement. Movements outside this area will be measured by the analog inputs reading two potentiometers per joystick. Triggers are measured by analog inputs reading one potentiometer per trigger. All joystick movements/variables are sent as 1 byte each, in a single transmission, multiple times per second. Triggers are the same.

Source code for controller here  (Only transmits trigger and joystick movements currently)

A complete rewrite of JunkBot code seemed in order, since controlling it with a proper controller and coding it differently could simplify things greatly. That is in progress, but movement is pretty much done:

Basic JunkBotX source here  (comment out SD card initialization if not hooked up)

UPDATE:

JunkBotX_SD source (working code, but in progress) here
- SD Card logging of movements
- fwd/rvs playback

Controller Source to accommodate record/playback  (B and Y buttons) here

My Custom Zephyr + Arduino Build for Arduino Uno Q: Adding Zephyr Networking to the Mix

 My Custom Zephyr + Arduino Build for Arduino Uno Q: Adding Zephyr Networking to the Mix Using RF24Ethernet with native Zephyr networking  F...