Attiny85 analogread + pwmout

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
gradeschool
 
Posts: 34
Joined: Fri May 23, 2008 2:46 pm

Attiny85 analogread + pwmout

Post by gradeschool »

hello,

i'm new to the Attiny85. i can program it- i can get it to analogWrite pwm out. but i can't get it to analogRead. this is my test circuit:

Image

and this is my code

Code: Select all

// to run on attiny85

const byte pwmPin = 0;
const byte analogInPin = A2;

void setup() {
  pinMode(pwmPin, OUTPUT);
}

void loop() {
  int analogIn = analogRead(analogInPin);
  analogWrite(pwmPin, analogIn);
}
i read 1023 on my arduino micro- when i think i should be reading something like 790 which should equate to 3.86v.

i must be doing something very wrong...?

1chicagodave
 
Posts: 564
Joined: Wed Jun 19, 2013 3:35 am

Re: Attiny85 analogread + pwmout

Post by 1chicagodave »

Yes. The pin numbering for the analog inputs does not coincide with pin numbering for other pin uses.
Pinout
Pinout
image.jpg (37.44 KiB) Viewed 1847 times
See this page for more on ATtiny85 pinouts -
http://learn.adafruit.com/introducing-trinket/pinouts

User avatar
gradeschool
 
Posts: 34
Joined: Fri May 23, 2008 2:46 pm

Re: Attiny85 analogread + pwmout

Post by gradeschool »

thanks for your reply. i'm still very confused though!

i think i am using the proper pins- both in the wiring and in my code.

GPIO #0 - this is connected to PB0 on the ATtiny85. This pin can be used as a PWM output, and is also used for I2C data, and SPI data input.
GPIO #4 - this is connected to PB4 on the Attiny85. this pin is used for USB programming, but it can also be used as a PWM analog output and an analog input known as Analog A2

can you elaborate- or help me by clarifying where i've made a misstep? thank you.

1chicagodave
 
Posts: 564
Joined: Wed Jun 19, 2013 3:35 am

Re: Attiny85 analogread + pwmout

Post by 1chicagodave »

You're correct, I was misreading your diagram... :oops:

I believe the problem is that of 10 vs 8 bits.

The ADC is 10-bit (0-1023). The PWM is 8-bit (0-255).

If you analogWrite the 10-bit ADC value, anything over 255 will be read as 5V on micro.

You need to add something like this between the analogRead() and analogWrite() functions -

Code: Select all


map(analogIn, 0, 1023, 0, 255);

This will "remap" the values from 10 bit to 8 bit while maintaining the relative value. (0 = 0) (1023 = 255).

User avatar
gradeschool
 
Posts: 34
Joined: Fri May 23, 2008 2:46 pm

Re: Attiny85 analogread + pwmout

Post by gradeschool »

even with the addition of re-mapping the values, i still get the same results.

when i read the voltage (with multimeter) on the pins, i get

5v VCC
5v PB0
3.85v A0
0v gnd

i think i'm definitely missing something elementary here.

User avatar
gradeschool
 
Posts: 34
Joined: Fri May 23, 2008 2:46 pm

Re: Attiny85 analogread + pwmout

Post by gradeschool »

here is another way to look at my problem. when i try this on the attiny - not using analogRead- just outputting a pwm value of 22-

Code: Select all

void loop() {
  pinMode(0, OUTPUT);
  analogWrite(0, 22);
}
it works properly. i get a reading of 88 (22*4) which is proper. if i bypass my rc filter - i get my digital pulsing- a series of 0s and 1023s. which is proper. and if i take a reading on the 0 pin with my multimeter- i get .44v, which is proper.

but when i try both analogRead and pwm out- -- when i run this on the attiny:

Code: Select all

void loop() {
  pinMode(0, OUTPUT);
  int analogIn = analogRead(A2);
  analogWrite(0, A2);
}
i get an an analogin reading of 1023 and a multimeter verification on pin0 of 5v. i verified again the voltage on pin4 (A2- also physical pin 3) and it is 3.85v.

i'm trying to reduce the circuit and the code down to the bare minimum to decipher where my problem is, but i can't seem to find it.

User avatar
gradeschool
 
Posts: 34
Joined: Fri May 23, 2008 2:46 pm

Re: Attiny85 analogread + pwmout

Post by gradeschool »

1chicagodave-

you were absolutely correct! it was re-mapping. i must have hurried something when i first tested your suggestion. i've just re-tested, and it's working exactly like i thought it should.

Code: Select all

// to run on attiny85

const byte pwmPin = 0;
const byte analogInPin = A2;

void setup() {
}

void loop() {
  pinMode(pwmPin, OUTPUT);
  int analogIn = analogRead(analogInPin);
  analogIn = map(analogIn, 0, 1023, 0, 255);
  analogWrite(pwmPin, analogIn);
}
why am i not setting the input pin during the setup() call- i'm trying some variations... i think it'll work fine.

thanks again!

1chicagodave
 
Posts: 564
Joined: Wed Jun 19, 2013 3:35 am

Re: Attiny85 analogread + pwmout

Post by 1chicagodave »

Great!
why am i not setting the input pin during the setup() call
The pinMode() function configures the port as an input or an output. Technically, it configures the DDR (Data Direction Register) which corresponds to the pin that is specified by pinMode(). If the bit of corresponding DDR is 0, the pin is configured as an input. If the bit of DDR is 1, the pin is configured as an output. The initial values of DDRs are zero, which is INPUT.

Basically, all pins just default to input 'mode'.

The actual code which is run when calling pinMode() looks something like this -

Code: Select all

void pinMode(uint8_t pin, uint8_t mode)
{
        uint8_t bit = digitalPinToBitMask(pin);
        uint8_t port = digitalPinToPort(pin);
        volatile uint8_t *reg, *out;

        if (port == NOT_A_PIN) return;

        reg = portModeRegister(port);
        out = portOutputRegister(port);

        if (mode == INPUT) { 
                uint8_t oldSREG = SREG;
                cli();
                *reg &= ~bit;
                *out &= ~bit;
                SREG = oldSREG;
        } else if (mode == INPUT_PULLUP) {
                uint8_t oldSREG = SREG;
                cli();
                *reg &= ~bit;
                *out |= bit;
                SREG = oldSREG;
        } else {
                uint8_t oldSREG = SREG;
                cli();
                *reg |= bit;
                SREG = oldSREG;
        }
}
So...unless you have a need to call it more than once throughout a sketch, it's best to keep it in setup() -- Helps to avoid excess processing time, memory usage, and possible errors. Keeps the looping code simpler.

User avatar
timoteo_mendes
 
Posts: 2
Joined: Wed Mar 25, 2015 9:50 am

Re: Attiny85 analogread + pwmout

Post by timoteo_mendes »

Hello all,
I am having some troubles about reading the correct value in analog 1 or the P2 of the tiny.
Do i have to performe some program of fuses in order to work?
I am using also the SoftwareSerial in order to debug the sistem and to work i have burn the fuses to be 8Mhz internal clock.
Here is the code:

Code: Select all

#include <SoftwareSerial.h>

SoftwareSerial TinySerial(3, 4); // RX, TX

void setup() {
  pinMode(A1,INPUT); //analog in batt
  pinMode(0,OUTPUT); //PWM1
  pinMode(1,OUTPUT); //PWM2
  pinMode(3,INPUT); //RX
  pinMode(4,OUTPUT); //TX
  TinySerial.begin(9600);
  TinySerial.println("Serial Connected");
}

void loop() {

  int Vbatt = 0;
  Vbatt = analogRead(A1);
  TinySerial.println(Vbatt);
  delay(200);
}
Any help is very much apreciate.
Thanks,
Timóteo

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

Return to “Microcontrollers”