Friday, April 28, 2006

Averaging, Smoothing




I used Flex sensor and same Processing code for Sensors and Time.

Averaging and finding the median Pic Code

' Analog median and average
' by Tom Igoe

' This program reads an analog input and gives the average of 9 readings,
' and sorts the list of readings and delivers the median number.

' Created 17 October 2005
' Updated

' Define ADCIN parameters
DEFINE ADC_BITS 10 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (3=rc)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in uS

TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %10000010 ' Set PORTA analog and right justify result


numReadings con 9 ' number of samples to take
median var byte ' median of the sorted samples
readingNumber var byte ' counter for the sample array
' serial variables and constants:
tx var portc.6
rx var portc.7
inv9600 con 16468

' variables for subroutines:
i var byte
j var byte
position var byte
analogValues var word[numReadings]
total var word
average var word
out var byte
in var byte
swapper var word

main:
for readingNumber = 0 to (numReadings - 1)
' get the reading:
adcin 0,analogValues[readingNumber]
' increment the counter:
readingNumber = readingNumber + 1
next
' sort the array using a bubble sort:
gosub bubbleSort

' get the middle element:
median = analogValues[numReadings / 2]

' print the results:
' print the array, nicely ASCII-formatted:
serout2 tx, inv9600,["Array: ["]
for j = 0 to (numReadings - 1)
serout2 tx, inv9600, [DEC analogValues[j], ", "]
next
serout2 tx, inv9600,["]", 10, 13]
' average the array:
gosub averageArray
serout2 tx, inv9600, ["Average: ", DEC average, 10, 13]
serout2 tx, inv9600, ["Median: ", DEC median, 10, 13]
GOTO MAIN

' average the values in the array:
averageArray:
total = 0
average = 0
for i = 0 to (numReadings - 1)
total = total + analogValues[i]
next
average = total/numReadings
RETURN

bubbleSort:
for out = 0 to (numReadings - 2) ' outer loop
for in = out+1 to (numReadings - 1) ' inner loop
if analogValues[out] > analogValues[in] then 'out of order?
swapper = analogValues[out]
analogValues [out] = analogValues[in]
analogValues[in] = swapper
endif
next
next
return

Next one is Eliminating the pick points

Written in PicBasic Pro, tested on a PIC 18F252:


' Analog smoothing algorithm
' by Tom Igoe

' This program reads an analog input and smooths out the result by averaging
' the result with past values of the analog input.

' uses a potentiometer on analog in 2 to generate the value for alpha,
' the number of samples to average.

' n.b. the variable "smoothed" needs to be a global, since it's modified
' each time a new smoothing is done. So if you want to use this for multiple
' inputs, you'll need a "smoothed" variable for each input.

' Created 17 October 2005
' Updated 27 March 2006


' Define ADCIN parameters
DEFINE ADC_BITS 10 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (3=rc)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in uS

TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %10000010 ' Set PORTA analog and right justify result


analogVal var word ' the value from the ADC
smoothed var word ' a nicely smoothed result. This needs to be a global variable
byteVar var byte ' a byte variable to send out serially
alpha var byte ' the number of past samples to average by
trimPotValue var word ' the trimmer pot input

' serial variables and constants:
tx var portc.6
rx var portc.7
inv9600 con 16468

' Variables for subroutines:
i var byte
LEDPin var portb.7

gosub blink

main:
' read the trim pot to determine alpha between 1 and 10:
adcin 1, trimPotValue
alpha = (trimPotValue / 114) + 1
' get an analog reading:
adcin 0, analogVal
' smooth it:
gosub smoothValue

' to see the difference, try outputting analogVal
' instead of smoothed here, and graph the difference.
' divide by 4 to print the result as a byte:
byteVar = smoothed /4
serout2 tx, inv9600, [byteVar]

' delay before next reading
pause 10
goto main

' Blink the reset LED:
blink:
for i=0 to 3
high LEDPin
pause 200
low LEDPin
pause 200
next
return

' Smooth out an analog reading:
smoothValue:
if (analogVal > smoothed) then
smoothed = smoothed + (analogVal - smoothed)/alpha
else
smoothed = smoothed - (smoothed - analogVal)/alpha
endif
return

Processing Code(same as Sensors and time)

import processing.serial.*;

Serial myPort; // The serial port

// initial variables:
int i = 1; // counter
int inByte = -1; // data from serial port

void setup () {
size(400, 300); // window size

// List all the available serial ports
println(Serial.list());
// I know that the third port in the serial list on my mac
// is always my Keyspan adaptor, so I open Serial.list()[2].
// Open whatever port is the one you're using.
myPort = new Serial(this, Serial.list()[0], 9600);

// set inital background:
background(0);
}
void draw () {
if (myPort.available() > 0) {
inByte = myPort.read();
serialEvent();
}
}

void serialEvent () {
// draw the line:
stroke(0,255,0);
line(i, height, i, height - inByte);
// at the edge of the screen, go back to the beginning:
if (i >= width) {
i = 0;
background(0);
}
else {
i++;
}
}

Friday, April 14, 2006