Analog Input

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
bman22
 
Posts: 75
Joined: Mon Dec 22, 2008 2:38 am

Analog Input

Post by bman22 »

After seeing the arduino controlling a servo via potentiometer, i have been looking at doing it without the whole arduino. Im trying to make an tiny45 that currently emmits a 17.5khz frequency for the "mosquito" effect, be able to have a potentiometer controll the frequency of the sound by changing the timer setting. Sadly i know absolutely nothing about analog input, and i really only know how to edit other's peoples code. at the moment i only have a 2313, so i really only have the code for that at the moment. If somebody could help inform me about analog input, and if there is anything similar to the arduino command map so i can set the pot to change the value of a variable between two specific numbers. At the moment, the below code is all i have, and its for the 2313. Im pretty new to avr so im not quite sure how to change it to work with another chip.

Code: Select all

#include <avr/io.h>      // this contains all the IO port definitions
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <util/delay.h>

void delay_ms( uint16_t milliseconds)
{
   for( ; milliseconds > 0; milliseconds--)
   {
      _delay_ms( 1);
   }
} 

#define TIMER1_PRESCALE_1 1
#define TIMER1_PRESCALE_8 2
#define TIMER1_PRESCALE_64 3
#define TIMER1_PRESCALE_256 4
#define TIMER1_PRESCALE_1024 5

#define HEX__(n) 0x##n##UL
#define B8__(x) ((x&0x0000000FLU)?1:0)  \
               +((x&0x000000F0LU)?2:0)  \
               +((x&0x00000F00LU)?4:0)  \
               +((x&0x0000F000LU)?8:0)  \
               +((x&0x000F0000LU)?16:0) \
               +((x&0x00F00000LU)?32:0) \
               +((x&0x0F000000LU)?64:0) \
               +((x&0xF0000000LU)?128:0)
#define B8(d) ((unsigned char)B8__(HEX__(d)))

onst static int image[] = {
  B8(11111111),
  B8(00000000)
};

#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))
int imagesize = NUM_ELEM(image);
uint8_t j = 0;
SIGNAL( SIG_TIMER1_COMPA ) {
  if (j == 1)
  if (j >= imagesize)
    j = 0;

  PORTB = image[j];
  j++;
}

int main(void) {

  DDRB = 0xFF;
  TCCR1B = (1 << WGM12) | TIMER1_PRESCALE_1;
  OCR1A = 228;
  TIMSK |= 1 << OCIE1A;

  sei();

  while (1);
}

i tried guessing at what i might have to do to change the code to work for the 45. i don't know if it works.

Code: Select all

#include <avr/io.h>      // this contains all the IO port definitions
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <util/delay.h>

#define TIMER1_PRESCALE_1 1
#define TIMER1_PRESCALE_8 2
#define TIMER1_PRESCALE_64 3
#define TIMER1_PRESCALE_256 4
#define TIMER1_PRESCALE_1024 5

int j = 0;
SIGNAL( SIG_TIMER1_COMPA ) {
  if (j == 1)
  {
     PORTB.B1 = 1;
     j = 0;
  }
  else if (j == 0)
  {
     PORTB.B1 = 0;
     j = 1;
  }
}

int main(void) {

  DDRB = 0xFF;
  TCCR1B = (1 << WGM12) | TIMER1_PRESCALE_1;
  OCR1A = 228;
  TIMSK |= 1 << OCIE1A;

  sei();

The_Don125
 
Posts: 373
Joined: Tue Mar 06, 2007 11:51 pm

Re: Analog Input

Post by The_Don125 »

First: Code comments are extremely useful if you want other people to debug your code.

Second: The 2313 completely lacks an ADC, so you won't be reading any potentiometers with that chip, without building some sort of R-2R ladder or something.

Third: Check out this post for a code example that uses the analog to digital converter on a tiny45 (aka, what you need to read a potentiometer) http://forums.ladyada.net/viewtopic.php?p=48801#p48801

Fourth: If you want to save some money, go with the tiny25V instead, the code should easily fit.

bman22
 
Posts: 75
Joined: Mon Dec 22, 2008 2:38 am

Re: Analog Input

Post by bman22 »

well i worked on my code a bit, and using the atmel software and a tut on avrfreaks, i think im getting closer. Also, i was well aware of the lack of ADC on the 2313, that is why i was trying to convert the code to the 45 and add a function to deal with a variable frequency.

Code: Select all


#include <avr/io.h>      // this contains all the IO port definitions
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <util/delay.h>

#define TIMER1_PRESCALE_1 1
#define TIMER1_PRESCALE_8 2
#define TIMER1_PRESCALE_64 3
#define TIMER1_PRESCALE_256 4
#define TIMER1_PRESCALE_1024 5

int j = 0;
SIGNAL( SIG_TIMER0_COMPA ) {
  if (j == 1)              //If port b bit 1 was just off, turn it on
  {
     PORTB = 0b010000;
     j = 0;
  }
  else if (j == 0)        //Oposite
  {
     PORTB = 0b000000;
     j = 1;
  }
}

int main(void) {

  ADCSRA |= (0 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Set ADC prescalar to 8 - 125KHz sample rate @ 1MHz 

  ADMUX |= (1 << REFS0); // Set ADC reference to AVCC 
  ADMUX |= (1 << ADLAR); // Left adjust ADC result to allow easy 8 bit reading 

  // No MUX values needed to be changed to use ADC0 

  ADCSRA |= (0 << ADATE);  // Set ADC to Free-Running Mode 
  ADCSRA |= (0 << ADIF);
  ADCSRA |= (0 << ADIE);

  ADCSRA |= (1 << ADEN);  // Enable ADC 
  ADCSRA |= (1 << ADSC);  // Start A2D Conversions

   
  int time = 500 - ADCH;            //take the ADC value and subtract it from 500, to get a number that increases with adc decrease. 500 fit the frequency range correctly
  DDRB = 0b010000;
  TCCR0B = (1 << WGM02) | TIMER1_PRESCALE_1;
  OCR0A = time;                 //set the timer value to that number calculated before
  TIMSK |= 1 << OCIE1A;

  sei();
}


do you think this will accomplish what i am trying, once it is finished?

edit: i got the code to atleast compile with this. i still get a SIG_TIMER0_COMPA appears to be a misspelled signal handler warning though

bman22
 
Posts: 75
Joined: Mon Dec 22, 2008 2:38 am

Re: Analog Input

Post by bman22 »

edit: i figured this part out

edit 2: i looked in both the definitions for the 2313 and the 25/45 and the closest thing to SIG_TIMER1_COMPA was TIMER0_COMPA_vect (im using timer 0 on the 25/45 code). will that do the trick?

mtbf0
 
Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am

Re: Analog Input

Post by mtbf0 »

SIG_TIMER1_COMPA is deprecated.

TIMER0_COMPA_vect is what you use, now.

the syntax is

Code: Select all

ISR (TIMER0_COMPA_vect) {
you might want to take a look at the avr-libc docs.

bman22
 
Posts: 75
Joined: Mon Dec 22, 2008 2:38 am

Re: Analog Input

Post by bman22 »

so, are you suggesting i replace the SIGNAL(TIMER0_COMPA_vect) { with a ISR(TIMER0_COMPA_vect) {? i definitely don't keep up with current ways to do things. in html, i still use font tags overe css, and font tags have been depreciated for years.

bman22
 
Posts: 75
Joined: Mon Dec 22, 2008 2:38 am

Re: Analog Input

Post by bman22 »

well, in the mean time, i tried to do one by setting the value from the adc with a digital input instead. each time you set one pin high, it counts up. Well i tried it, and it just stays at the same frequency (i checked it with my oscilliscope). the code i have to do it with the digital input is for the 2313 and is :

Code: Select all

#include <avr/io.h>      // this contains all the IO port definitions
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <util/delay.h>

#define TIMER1_PRESCALE_1 1
#define TIMER1_PRESCALE_8 2
#define TIMER1_PRESCALE_64 3
#define TIMER1_PRESCALE_256 4
#define TIMER1_PRESCALE_1024 5
#define HEX__(n) 0x##n##UL
#define B8__(x) ((x&0x0000000FLU)?1:0)  \
               +((x&0x000000F0LU)?2:0)  \
               +((x&0x00000F00LU)?4:0)  \
+((x&0x0000F000LU)?8:0)  \
               +((x&0x000F0000LU)?16:0) \
               +((x&0x00F00000LU)?32:0) \
               +((x&0x0F000000LU)?64:0) \
+((x&0xF0000000LU)?128:0)
#define B8(d) ((unsigned char)B8__(HEX__(d)))

const static int image[] = {
  B8(11111111),
  B8(00000000)
};

#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))
int imagesize = NUM_ELEM(image);

uint8_t j = 0;
SIGNAL( SIG_TIMER1_COMPA ) {
  if (j >= imagesize)
    j = 0;
  PORTB = image[j];
  j++;
}

long map(long x, long in_min, long in_max, long out_min, long out_max)    //this is the arduino map function. i got it off the arduino site
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

int timer_calculate(int speed)             //calculates the value the timer needs to be at to produce that pitch
{
	speed = 2 * speed;                    //since each setting of either on or off takes a whole cycle, i need to double the frequency 
	return F_CPU / speed;                //returns the cpu clock from the makefile divided by the desired speed
}

int main(void) {

  int high = 0;       //holds the wanted high frequency
  int low = 0;        //holds the wanted low frequency
  int freq = 0;       //holds the current value between 0 and 255. don't know why i named it that
  int time = 0;      //holds the needed timer length
  DDRB = 0xFF;     //All port b output
  PORTB= 0x00;    //all port b off
  DDRD = 0x00;     //all port d input
while(1){
  if (PIND0 == 1 && freq < 255) {    //if PIND0 is high, and the value of freq is below 255, add one to freq
	  freq++;
  }
  else if(PIND1==1 && freq > 0) {   //if PIND1 is high, and the value of freq is above 0, subtract one from freq
	  freq--;
  }
  low = 10000;         //low frequency in hz
  high = 20000;        //high frequency in hz
  low = timer_calculate(low);        //calculate the timer length for low frequency
  high = timer_calculate(high);      //calculate the timer length for high frequency
  time = map(freq, 0, 255, low, high);    //map the value of freq to between the low frequency and the high frequency
  TCCR1B = (1 << WGM12) | TIMER1_PRESCALE_1;
  OCR1A = time;
  TIMSK |= 1 << OCIE1A;

  sei();
  }

}
that doesn't work. why not?

edit: i looked over it about 10 times, fixed some problems and still not working correctly. I also added comments to the above code, because it has been suggested if i want help, it would be best if people could figure out what my code was doing.

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”