Boogie Ball: Code Snippet

The ball’s rotation is done through the implementation of a Timer Compare Interrupt. Each time this interrupt occurs, a global flag is set in the code. The main program loop checks this flag each loop and updates the servo position each time it is set. The flag is then cleared and the loop continues until the interrupt occurs again. A snippet of the code that changes the servo position is shown below along with a video of the spinning.

Continue reading Boogie Ball: Code Snippet

8-Button Piano – Interrupt Driven Code

Our 8-Button Piano is driven purely by interrupts. Utilizing the in-class example for button handling, we configured all 8 of our buttons as input using the GPIO ports available on the ATMega328P Xplained Mini microcontroller. In order to achieve a level of attainable modularity with our design, we utilized predefined macros to indicate the data direction register, port, and pin numbers for each of our buttons.  Continue reading 8-Button Piano – Interrupt Driven Code

Two-Lock Safe: Locking Code

Servo Code:

Two Lock Safe – Overview
#include <avr/io.h> #include <util/delay.h> //Function Prototypes void lock(); void unlock(); void init_PWM(); void setDDR(int b, int c, int d); void lock(){ init_PWM(); //assume lock = -90 degrees = 1 ms pulse OCR1A = 0x946E; _delay_ms(10000); setDDR(0,0,0); } void unlock(){ init_PWM(); //assume unlock = 0 degrees = 1.5 ms pulse OCR1A = 0x9086; _delay_ms(10000); setDDR(0,0,0); } void init_PWM(){ //set data direction on port b, other ports are off setDDR(0xFF, 0, 0); //set waveform generation mode (mode #14 on datasheet: fast pwm) TCCR1A |= 1<<WGM11 | 0<<WGM10; TCCR1B |= 1<<WGM12 | 1<<WGM13; //set output mode (inverted, starts low & switches to high on compare match) TCCR1A |= 1<<COM1A1 | 1<<COM1A0; //set prescaler (clk/1, no prescaler) //001 -> clk/1 //010 -> clk/8 TCCR1B |= 0<<CS12 | 1<<CS11 |0<<CS10; //set period (20,000 counts per second -> 20ms period) ICR1 |= 0x9C3E; } void setDDR(int b, int c, int d){ DDRB = b; DDRC = c; DDRD = d; } int main(void) { while(1){ lock(); unlock(); } }

Code used to program the microcontroller to set the servo to lock and unlock.

Electronic Safe: Code Snippet

void StoreKey(char *str)

{

ee_up = 0x00;

ee_low = ee_up + 5;

while (*str)

{

bit = *str++;

EEPROM_Write();

ee_up =ee_up+10; //test

ee_low = ee_up+5;

}

lastaddress = ee_up;

}



void GetKey(void)

{

ee_up = 0x00;

ee_low = ee_up +5;

while (ee_up != lastaddress)

{

EEPROM_Read();

UART_Put();

ee_up = ee_up +10;

ee_low = ee_up +5;

}

}

The code above is used to store a variable length PIN in EEPROM and retrieve it when needed. It starts at address 0x00 and increments by 10 for every successful digit. Once the PIN is stored it saves the last used address into a variable so the GetKey() function knows when to stop.

 

Laser Harp-Code Snippet

This snippet of code reads the pins on PORTD. If a pin on PORTD is high, “data” will be larger than 0 and will get stuck in the while loop until the pins on PORTD are low again.  Before entering the loop, global interrupts are enabled which allows the interrupt that generates the tone to be called. Then after all pins on PORTD are low, global interrupts are disabled and the program continues. This is used so that a constant tone will be played for however long a laser is blocked.

MIDI Controller: Code Snippet

This is a snippet of our code, more specifically, it is a MIDI handler function that we wrote to handle the “On Note” MIDI event. It takes a channel as a parameter, assigns it to thee appropriate voice, and then checks if the voice is a square channel or drum channel. From here, the code handles the appropriate channel, updates the pitch of the note, and sets the attenuation of the note.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Image result for undertale dog

 

Frequency Spectrum Analyzer – Code

Below is the entirety of the source code, but the magic happens within this segment.

// Loop for the number of samples to take from the analog signal
for (int i = 0; i < 128; i++) {
// Store the value from the from analog pin 0
val = analogRead(A0);
// Store a modified value into the arrays
data[i] = val / 4 - 128;
im[i] = 0;
}

// Run the fixed FFT function on the arrays
fix_fft(data, im, 7, 0);

Here you can see that the loop runs 128 times and this corresponds to reading the analog input 128 times. This data is then stored inside a data array which gets passed to the fix_fft library function. Within this function, it converts each of the analog values into their corresponding frequency levels. Almost all of the rest of the code is to control the LEDs themselves

/* This section of code includes the necessary libraries to run our code properly
// Adafruit_NeoPixel.h – Gives us commands to initialize and operate the NeoPixel LEDs
// fix_fft.h – Gives us commands to run the Fast Fourier Transform (FFT)
// avr/power.h – Reduces power consumption if the board runs AVR architecture */
#include <Adafruit_NeoPixel.h>
#include “fix_fft.h”
#ifdef __AVR__
#include <avr/power.h>
#endif

// Defines a global variable to store what pin the LED information will be sent from
#define PIN 0

// Variable arrays to store data from the analog signals and run through the FFT
char im[128], data[128];

/* Creates an instance of our strip of LEDs to run operations on
// Parameter 1 = Number of pixels in strip
// Parameter 2 = Arduino pin number to send data (most are valid)
// Parameter 3 = pixel type flags, add together as needed:*/
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

// The method that is run on start up for the board
void setup(){
// Sets the reference for the analog signals to the 5V default
analogReference(DEFAULT);

// Initializes the LED strip
strip.begin();

// Display the latest colors on the LED strip
strip.show();
};

// The method that runs repeated until the board shuts off
void loop(){
// Sets the minimum and maximum ADC values
int min=1024, max=0,val=0;

// Loop for the number of samples to take from the analog signal
for (int i = 0; i < 128; i++) {
// Store the value from the from analog pin 0
val = analogRead(A0);
// Store a modified value into the arrays
data[i] = val / 4 – 128;
im[i] = 0;
// If the incoming value exceeds the min or max, replace them
if(val>max)
max=val;
if(val<min)
min=val;
}

// Run the fixed FFT function on the arrays
fix_fft(data, im, 7, 0);

// Run the clearBars function to turn all LEDs off before adjusting levels
clearBars();

// Loop for each column of the visualizer (Indexed starting at 1 to avoid FFT errors)
for (i = 1; i <= 10; i++) {
// Store a modified version of the data values to filter noise and hum
double dat = sqrt(data[i] * data[i] + im[i] * im[i]);
// Send the data to the respective bar the visualizer to set its height
setBar(i-1, dat);
}
};

// A method that sets the height of a given column to represent the given data value
void setBar(int bar, double dat){
// Stores the bottom LED ID for the column
int bottom;
// Stores the threshold that is modified to compare all levels
int threshold = 15;
// Save six preset colors for each row of the visualizer
uint32_t row6 = strip.Color(255, 0, 0);
uint32_t row5 = strip.Color(255, 30, 0);
uint32_t row4 = strip.Color(255, 63, 0);
uint32_t row3 = strip.Color(45, 255, 20);
uint32_t row2 = strip.Color(10, 255, 10);
uint32_t row1 = strip.Color(0, 255, 0);

// Checks if given bar is an even number
if(bar % 2 == 0){
// Set bottom to the address of the first LED in the column
bottom = 6*bar;

/* Checks if the given data value is above certain thresholds, and if its true // // enable the corresponding LED with the rows color. */
if((dat*10) >= threshold*5){
strip.setPixelColor(bottom+5, col6);
}
if((dat*10) >= threshold*4){
strip.setPixelColor(bottom+4, col5);
}
if((dat*10) >= threshold*3){
strip.setPixelColor(bottom+3, col4);
}
if((dat*10) >= threshold*2){
strip.setPixelColor(bottom+2, col3);
}
if((dat*10) >= threshold){
strip.setPixelColor(bottom+1, col2);
}
strip.setPixelColor(bottom, col1);

// Run the show function of the LED strip to show the intensity change
strip.show();
}
else{
// Set bottom to the address of the first LED in the column
bottom = 6*bar+5;

/* Checks if the given data value is above certain thresholds, and if its true // // enable the corresponding LED with the rows color. */
if((dat*10) >= threshold*5){
strip.setPixelColor(bottom-5,col6);
}
if((dat*10) >= threshold*4){
strip.setPixelColor(bottom-4, col5);
}
if((dat*10) >= threshold*3){
strip.setPixelColor(bottom-3, col4);
}
if((dat*10) >= threshold*2){
strip.setPixelColor(bottom-2, col3);
}
if((dat*10) >= threshold){
strip.setPixelColor(bottom-1, col2);
}
strip.setPixelColor(bottom, col1);

// Run the show function of the LED strip to show the intensity change
strip.show();
}
};

// A method to clear the colors of all LEDs
void clearBars(){
// Loop for every LED in the LED strip
for(int i = 0; i < 60; i++){
// Set the LEDs color to zeros to turn them off
strip.setPixelColor(i, 0, 0, 0);
}
};

Pong Video Game Software

When the game was played, the ball appeared to hit the floor and ceiling; however, it did not actually collide with either. Instead, the ball’s range of motion was limited to bounce the ball from the top to the bottom. This was a y-axis range of 88-502, and when the ball reached either limit it reversed its direction. In order to make the ball collide with the floor and ceiling, both would have needed to be sprites (moving images), then pygame would have to check for a collision in each frame. This process would have been similar to the collision of the ball with the paddle, but it was simpler to limit the ball’s vertical range of motion.

Even though the ball did not actually collide with the bounds of the game, it did collide with the paddles. The function that checked for a collision was “spritecollide”, which was included in the pygame library. When a collision occurred, an empty list “block_hit_list” was filled with whichever object the ball collided with when a collision was detected. The parameters of this function included a list of both players, the reference to the ball object, and “False” which told the program to not delete the player object that the ball hit.

Temperature-Controlled Fan: ADC-Reading Code

I’ve got something super exciting to share: our temperature sensor code! The code retrieves the current ADC value by calling the function ADC_Get() , then interprets that data based on the temperature sensor documented output voltage.  ‘t’ is a global float variable. ‘fanSpeed’ is a global int value. Possible applications: converting float and integer types to character strings for output over serial connections or LCD output.

void Get_Temp(void) 
{
 
 int k = 0; //used to offset output, in case of negative temperatures
 float celcius; // Anders C.
 float fahrenheit; // Daniel Gabriel F.
 float kelvin; // William Thompson, 1st Barron K. 
 float v = 0.0; //voltage
 char temp[17]; //string for output to LCD
 
 for (int i = 0; i&lt; 16; i++)
 {
      temp[i] = 32; //pad output string with spaces
 }
 temp[16]='\0'; //null terminator for c-style string
 
 ADC_Get();
 Acc = (((int)HADC) * 0x100 + (int)(LADC));
 //temperature sensor rated output range: 
 //  100mV to 1750mV (-40 to 125°C)
 if (Acc &gt; 20 &amp;&amp; Acc &lt; 359) 
 {
      // Convert ADC output to fraction of Vcc. (5V)
      v = (Acc/1023.0)*(5.0); 
      // per specifications 10mV / °C (100° = 1 Volt, 750mV @ 25°C)
      celcius = (v - 0.5)*100.0; 
      kelvin = 273.15 + celcius; // celcius to kelvin
      fahrenheit = celcius * 9.0/5.0 + 32.0; // celcius to fahrenheit
      t = fahrenheit;
 
      if(t&lt;0)
      {
           t*=-1;
           k = 1; //offset display by 1, to make way for minus sign
           temp[0] = '-';
      }
      else
      {
           k = 0;
           temp[6] = 32;
      }
 
      int p = (int)(t*100.0); // float * 100, then cast to type int.
 
      //Note: 48 is the ASCII offset of '0' (49 = '1', 50 = '2', etc.)
      temp[(5+k)] = p % 10 + 48; //pull off hundredths decimal place. 
      p /= 10;
      temp[(4+k)] = p % 10 + 48; //pull off tenths decimal place
      p /= 10;
      temp[(3+k)] = '.';
      temp[(2+k)] = p%10 + 48;
      p/=10;
      if (p&gt;=0) {
           temp[1+k] =p%10 +48;
           p/=10;
      }
      else
           temp[1+k]='0';
      if (p&gt;=0){
           temp[0+k] = p +48;
      }
      else
           temp[0+k] = '0';

      if (t &gt; targetTemp) // max operating temperature has been exceeded
      {
           //display fan output speed
           temp[13]= fanSpeed / 10 % 10 +48;
           temp[14]= fanSpeed % 10 + 48;
           char msgStrFan[5] = {"Fan=%"};
           for (int i = 9; i &lt; 16; i++)
           {
                temp[i] = msgStrFan[i];
                if(i == 12) i = 15; //skip index 13,14
                temp[i]= msgStrFan[i];
           }
      }
      if (fanSpeed &gt; 99) //fanspeed has reached maximum
      {
           //for a little fun, after the fan has reached
           //maximum speed, we output text to the display
           //until the fan speed reaches &lt;60% load
 
           iZombie = 1; //locks output until fan speed &lt; 60%
           char msgStr1[16] = {"He's dead, Jim."};
           for (int i = 0; i &lt; 16; i++)
           {
                temp[i] = msgStr1[i];
           }
      }
      if (iZombie == 1)
      {
           if (fanSpeed &gt;80)
           {
                char msgStr1[16] = {"He's dead, Jim."};
                for (int i = 0; i &lt; 16; i++)
                {
                     temp[i] = msgStr1[i];
                }
 
           } else if (fanSpeed &gt;60)
                {
                     char msgStr2[16] = {"... could he be?"};
                     for (int i = 0; i &lt; 16; i++)
                          {
                               temp[i] = msgStr2[i];
                          }
 
                } else if (fanSpeed &gt;0)
                     {
                          char msgStr3[16] = {"He. Is. ALIVE !!"};
                          for (int i = 0; i &lt; 16; i++)
                          {
                               temp[i] = msgStr3[i];
                          }
                          iZombie = 0;
                     }
           }
      LCD_Puts(temp); //output character string to LCD
      Wait(); // This function just limits the refresh rate of the LCD
      Wait(); // If the refresh rate is too fast, the characters are dim
  } 
}

Plant Watering System: Code

Hey there Embedded Fans!

Progress is being made on our plant watering apparatus! As of late, the Unknowns have their code in progress, and we’ve gotten our motor driver to work! In order to do this, we’ve sent a high and low signal to two of the input pins on the driver (from pins D6 and D7), and sent a high signal to the enable pin (from pin D5) ! See our code snippet for super cool and exciting bit shifting operations!

But… don’t listen to me – see for yourself!

Soon our plants will never go thirsty again! :,)