Pin Programming

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am new to programming with microcontrollers. I have built a line sensor from 3 photoresistors sort of like this setup http://mechatronics.mech.northwe....

I have measured the voltages on the breadboard and I am trying to read the voltage drop from the outside photoresistors (not the center one (still hooked up to the microcontroller)) here is a link to a top view of the bread board and the side.
http://www.uccs.edu/~pcaldwel/Br...
http://www.uccs.edu/~pcaldwel/Br...

Unlike the bread board I am monitoring voltage levels on pins PB0 and PB2 while the other connection to the board is hooked up to ground. Here is a picture of the stk500 board.
http://www.uccs.edu/~pcaldwel/St...

Attached is what I have so far in code. I'm not sure how to read in voltage levels and monitor them... I figured out how to turn on pins and switch them from input pins to output pins. And thats all I've figured out so far. I hooked the breadboard up to the Agilent E3630A triple output dc power supply and the Agilent 34401A digital multimeter to check to see the breadboard was wired properly.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you trying to convert the variable voltage out of the photocell into a numeric value, or just detect whether it's high enough to be considered "on" (or low enough to be considered "off") and get a single bit as a result? For the former, you're going to need to configure the ADC to perform analog-to-digital conversions. For the latter, you need to use "PINB" instead of "PORTB" when you're reading from input pins. Also, be aware that comparing PINB to a constant value like 0x20 will only be true if all of its bits match those of the constant, so instead of

if(PINB==0x20)

you probably want to do

if(PINB & 0x20)

or, easier to read,

if(PINB & 1<<PINB5)

which makes it clear that you're testing pin five of port B. Also be aware that your line

if(PINB==0x04)

is apparently meant to test bit two of port B, but your earlier line

PORTB=0x00;
DDRB=0x07;

set all the bits of port B low and configured bits zero, one, and two of port B as outputs, so reading any of those three bits will usually result in zero.

Aaron T.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to convert variable voltage out of the photocell into a numeric value

I still don't entirely understand this.
Code:

PORTB=0x00;
DDRB=0x07; 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

from the pictures I see that your top supply rail is not connected to the bottom one.
this might be the problem.

also on my breadboard the supply rails are divided in 2 so I have to make a jumper in that line to.

so please check if this is also the problem with your bread board.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

throwsDumbUser wrote:
I still don't entirely understand this.
Code:

PORTB=0x00;
DDRB=0x07; 


What the first line does is sets every pin of port B to be low, meaning that if the pin is configured as an output, it will output zero volts, and if it's configured as an input, it will be high-impedance and its internal pull-up will be off. If you issued this command instead:
PORTB=0xFF

then each pin would be high, meaning that if it were an output it would put out Vcc, and if it were an input its internal pull-up would be on, pulling it up to Vcc.

The second line controls whether each pin is configured as an input or an output. Making DDRB 0x00 would configure all pins as inputs, while making it 0xFF would configure all pins as outputs.

It's easier to use these registers on a bit-by-bit basis, so it's clearer which pins are being changed. The example I gave before is one popular way to do it, using bit shifting. So, instead of

DDRB=0x07;

you could write

DDRB = (1<<DDB0) | (1<<DDB1) | (1<<DDB2);

As I mentioned before, though, if you want a numeric value proportional to the voltage and not just a binary one, you'll need to use the ADC to read the voltage.

Aaron T.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I want pin5 to have the voltage drop going into attiny85 then read the output voltage on pin2
All digital of course.

right now I have this

#include 

#define ADC_VREF_TYPE 0x20
#define LeftSensor PORTB.5 //input
#define MiddleSensor PORTB.4 //input
#define RightSensor PORTB.3 //input


  




// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=Out
// State5=T State4=T State3=T State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0x07;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFh
// OC1A output: Disconnected
// OC1B output: Disconnected
// Timer 1 Overflow Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
PLLCSR=0x00;
TCCR1=0x00;
GTCCR=0x00;
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;

// ADC initialization
// ADC Clock frequency: 920.000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Bipolar Input Mode: Off
// ADC Reverse Input Polarity: Off
// ADC Auto Trigger Source: None
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0&=0x03;
DIDR0|=0x00;
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x82;
ADCSRB&=0x5F;

while (1)
      {
        unsigned char lightSource0, lightSource1, lightSource2;

        lightSource0 = read_adc((unsigned char)LeftSensor);
        lightSource1 = read_adc((unsigned char)RightSensor);
        lightSource2 = read_adc((unsigned char)MiddleSensor);
        PORTB.2 =    LeftSensor ;
        PORTB.1 = RightSensor;
        PORTB.0 =   MiddleSensor;

       // if( lightSource <
      };
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First, like I mentioned previously, you need to read from "PINB", not "PORTB", when you're reading inputs. Second, the nomenclature you're using, like "PORTB.2", isn't valid in C nor in gcc, so it shouldn't compile. The correct way to do your defines is like I described earlier:

#define LeftSensor (PINB & 1<<PINB5)//input
#define MiddleSensor (PINB & 1<<PINB4) //input
#define RightSensor (PINB & 1<<PINB3) //input

Setting one bit based on another is a little more complicated, and different people probably have different preferred methods, but here's one:

        LeftSensor ? PORTB |= 1<<PB2 : PORTB &= ~(1<<PB2);
        RightSensor ? PORTB |= 1<<PB1 : PORTB &= ~(1<<PB1);
        MiddleSensor ? PORTB |= 1<<PB0 : PORTB &= ~(1<<PB0);

Aaron T.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Aaron T,

I was going through yours posting in this thread , Your's method of explanation is really superb.

Please post regularly as you joined this forum in 2005 and having just 47 posts. Please share your knowledge/views regularly.

Thanks,
Anmol Kumar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Looks like the poster is using CodeVision (or some other compiler) not gcc. That being the case a lot of the code could be produced by a setup wizard!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

read_adc needs a channel number as the argument, not a bit value (from a port). Your defines here

#define LeftSensor PORTB.5 //input 
#define MiddleSensor PORTB.4 //input 
#define RightSensor PORTB.3 //input 

indicates that you have the left sensor connected at ADC0, the middle at ADC2 and right at ADC3 hence this

        lightSource0 = read_adc((unsigned char)LeftSensor); 
        lightSource1 = read_adc((unsigned char)RightSensor); 
        lightSource2 = read_adc((unsigned char)MiddleSensor); 

should really be

        lightSource0 = read_adc(0); 
        lightSource1 = read_adc(3); 
        lightSource2 = read_adc(2); 

(but, depending on what you are doing, you can probably just correct the defines).

Also,

        PORTB.2 =    LeftSensor ; 
        PORTB.1 = RightSensor; 
        PORTB.0 =   MiddleSensor; 

Can you explain what you intend this to do?

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is reading the voltage drop from a Photo resistor on a voltage divider circuit. This goes into the attiny85 to read the voltage drop then outputs a 0 to 1 if the voltage changes from high to low. Example: say pin 5 has the (+) portion of Vcds connected to it and the (-) Vcds is connected to ground or (-) terminal on the battery. Assuming I have this wired correctly, from the attiny85 will moniter pin 5 untill the voltage level changes... and from that it will output a 0 or one on pin 2 depending.. There are 3 other light sensors on different pins but you get the point.

Here is the concept applied: http://www.uccs.edu/~pcaldwel/Concept.bmp
Here is a picture of the currently wired bread board:http://www.uccs.edu/~pcaldwel/BreadBoard1.JPG

Sorry if I sound like an idiot I've never done this before and I'm just assuming a lot.

I've updated my code in codevision:

/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.7f Standard
Automatic Program Generator
© Copyright 1998-2005 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
e-mail:office@hpinfotech.com

Project : linesensor
Version :
Date : 4/2/2008
Author : SiteLicense20Users,Univ.Colorado
Company : Colorado Springs CO80918 USA
Comments:


Chip type : ATtiny85
Clock frequency : 3.680000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/

#include 

#define ADC_VREF_TYPE 0x20
#define LeftSensor (PINB & 1<<PINB5)//input
#define MiddleSensor (PINB & 1<<PINB4) //input
#define RightSensor (PINB & 1<<PINB3) //input  




// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=Out
// State5=T State4=T State3=T State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0x07;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x00;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFh
// OC1A output: Disconnected
// OC1B output: Disconnected
// Timer 1 Overflow Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
PLLCSR=0x00;
TCCR1=0x00;
GTCCR=0x00;
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;

// ADC initialization
// ADC Clock frequency: 920.000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Bipolar Input Mode: Off
// ADC Reverse Input Polarity: Off
// ADC Auto Trigger Source: None
// Only the 8 most significant bits of
// the AD conversion result are used
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0&=0x03;
DIDR0|=0x00;
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x82;
ADCSRB&=0x5F;

while (1)
      {
        unsigned char lightSource0, lightSource1, lightSource2;
               
        
        PORTB.2 =    LeftSensor ;
        PORTB.1 = RightSensor;
        PORTB.0 =   MiddleSensor;
        
       /* lightSource0 = read_adc((unsigned char)LeftSensor);
        lightSource1 = read_adc((unsigned char)RightSensor);
        lightSource2 = read_adc((unsigned char)MiddleSensor);
        PORTB.2 =    LeftSensor ;
        PORTB.1 = RightSensor;
        PORTB.0 =   MiddleSensor;    */

       // if( lightSource <
      };
}