// //////////////////////////////////////////////
// ESP (CS 33301-001)
// Project 4: ADC and temp
//
// Kent State University
// Dept. of Computer Science
// Ean Dodge
// //////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
#include "servo.h"
#include "gpio.h"
#include "arduinoFFT.h"
#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
//////////////////////////////////////////////
//for ardiuno fft (mic detection)
#define SAMPLES 128
#define SAMPLING_FREQUENCY 2048
arduinoFFT FFT = arduinoFFT();
unsigned int samplingPeriod;
unsigned long microSeconds;
double vReal[SAMPLES]; //create for real values
double vImag[SAMPLES]; //for imaginary values
/////////////////////////////////////////////////////////
//for LCD
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
// Registers' Address Setting
unsigned char *ADMUX_ESP;
unsigned char *ADCSRA_ESP;
unsigned char *ADCSRB_ESP;
unsigned char *ADCL_ESP;
unsigned char *ADCH_ESP;
/* Which analog pin we want to read from. The pins are labeled "ADC0"
"ADC1" etc on the pinout in the data sheet. In this case ADC_PIN
being 0 means we want to use ADC0. On the ATmega328P this is also
the same as pin PC0 */
int ADC_PIN = 0;
/* This function just keeps the reading code out of the loop itself.
It takes the analog pin number as a parameter and returns the
analog reading on that pin as a result. */
uint16_t adc_read(uint8_t adcx);
void myPrint(double);
int val;
void loop() {
*ADCSRA_ESP |= 0b10000000;
// val = adc_read(ADC_PIN);
// Serial.print(val);
// Serial.print("\n");
// tone(8, NOTE_C4, 1000);
// delay(1000);
/////////////////////////////////////////////////
//for mic dec
if (detect) {
for (int i = 0; i < SAMPLES; i++) {
microSeconds = micros();
vReal[i] = adc_read(ADC_PIN);
vImag[i] = 0;
while (micros() < (microSeconds + samplingPeriod)) {
//do nothing
}
}
FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);
//Serial.println(peak);
lcd.setCursor(0, 0);
myPrint(peak);
detect = false;
}
}
uint16_t adc_read(uint8_t adcx) {
/* adcx is the analog pin we want to use. ADMUX's first few bits are
the binary representations of the numbers of the pins so we can
just 'OR' the pin's number with ADMUX to select that pin.
We first zero the four bits by setting ADMUX equal to its higher
four bits. */
*ADMUX_ESP &= 0xf0;
*ADMUX_ESP |= adcx;
/* This starts the conversion. */
*ADCSRA_ESP |= 0b01000000;
/* Finally, we return the converted value to the calling function. */
unsigned char cl = *ADCL_ESP;
unsigned char ch = *ADCH_ESP;
return (cl | (ch << 8));
}
void myPrint(double peak) {
if (peak < 275) {
lcd.print("You are playing");
lcd.setCursor(6, 1);
lcd.print("a C");
}
if (peak >= 275 && peak < 300) {
lcd.print("You are playing");
lcd.setCursor(6, 1);
lcd.print("a D");
}
if (peak >= 300 && peak < 340) {
lcd.print("You are playing");
lcd.setCursor(6, 1);
lcd.print("a E");
}
if (peak >= 340 && peak < 375) {
lcd.print("You are playing");
lcd.setCursor(6, 1);
lcd.print("a F");
}
if (peak >= 375 && peak < 425) {
lcd.print("You are playing");
lcd.setCursor(6, 1);
lcd.print("a G");
}
if (peak >= 425 && peak < 460) {
lcd.print("You are playing");
lcd.setCursor(6, 1);
lcd.print("a A");
}
if (peak > 460) {
lcd.print("You are playing");
lcd.setCursor(6, 1);
lcd.print("a B");
}
}