Go Down

Topic: Attiny85 sofeware PWM and analogread not be used simultaneously? (Read 6162 times) previous topic - next topic

merrywhale

Hi everyone, I found the following code here https://gist.github.com/funkfinger/954874 (It's for ATTiny85 3 channel software PWM to drive RGB LED)
I tried it in the ATtiny85. It works. :)  But I want to add a sensor through the analogRead, Unfortunately it isn't WORK. =( Whether the sofeware PWM and analogread not be used simultaneously?
Could someone can help me to give some advice? Thanks.

Code: [Select]
// based largely on Atmel's AVR136: Low-Jitter Multi-Channel Software PWM Application Note:
// http://www.atmel.com/dyn/resources/prod_documents/doc8020.pdf

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define CHMAX 3 // maximum number of PWM channels
#define PWMDEFAULT 0x00 // default PWM value at start up for all channels

#define RED_CLEAR (pinlevelB &= ~(1 << RED)) // map RED to PB0
#define GREEN_CLEAR (pinlevelB &= ~(1 << GREEN)) // map GREEN to PB1
#define BLUE_CLEAR (pinlevelB &= ~(1 << BLUE)) // map BLUE to PB2

//! Set bits corresponding to pin usage above
#define PORTB_MASK  (1 << PB0)|(1 << PB1)|(1 << PB2)

#define set(x) |= (1<<x)
#define clr(x) &=~(1<<x)
#define inv(x) ^=(1<<x)

#define RED PB0
#define GREEN PB1
#define BLUE PB2
#define LED_PORT PORTB
#define LED_DDR DDRB

#define SENSOR_PIN 2

void delay_ms(uint16_t ms);
void init();

unsigned char compare[CHMAX];
volatile unsigned char compbuff[CHMAX];

int r_val = 0x00;
int g_val = 0x55;
int b_val = 0xAA;
float dim = 1;

void setup()                   
{
  pinMode( SENSOR_PIN, INPUT );
}
void loop()                   
{
  init();
 
  int const rawVal = analogRead( SENSOR_PIN );  // It isn't works!
 
  int r_dir = 1;
  int g_dir = 2;
  int b_dir = 4;
 
  for(;;) {
    if (r_val > 254 - 1) {
      r_dir = -1;
    }
    if (r_val < 1 + 1) {
      r_dir = 1;
    }

    if (g_val > 254 - 3) {
      g_dir = -2;
    }
    if (g_val < 1 + 3) {
      g_dir = 2;
    }

    if (b_val > 254 - 4) {
      b_dir = -4;
    }
    if (b_val < 1 + 4) {
      b_dir = 4;
    }
   
    r_val += r_dir;
    g_val += g_dir;
    b_val += b_dir;

    compbuff[0] = r_val;
    compbuff[1] = g_val;
    compbuff[2] = b_val;

    delay_ms(50);
  }
}


void delay_ms(uint16_t ms) {
  while (ms) {
    _delay_ms(1);
    ms--;
  }
}

void init(void) {
  // set the direction of the ports
  LED_DDR set(RED);
  LED_DDR set(GREEN);
  LED_DDR set(BLUE);
 
  unsigned char i, pwm;

  CLKPR = (1 << CLKPCE);        // enable clock prescaler update
  CLKPR = 0;                    // set clock to maximum (= crystal)

  pwm = PWMDEFAULT;

  // initialise all channels
  for(i=0 ; i<CHMAX ; i++) {
    compare[i] = pwm;           // set default PWM values
    compbuff[i] = pwm;          // set default PWM values
  }

  TIFR = (1 << TOV0);           // clear interrupt flag
  TIMSK = (1 << TOIE0);         // enable overflow interrupt
  TCCR0B = (1 << CS00);         // start timer, no prescale

  sei();
}


ISR (TIM0_OVF_vect) {
  static unsigned char pinlevelB=PORTB_MASK;
  static unsigned char softcount=0xFF;

  PORTB = pinlevelB;            // update outputs
 
  if(++softcount == 0){         // increment modulo 256 counter and update
                                // the compare values only when counter = 0.
    compare[0] = compbuff[0];   // verbose code for speed
    compare[1] = compbuff[1];
    compare[2] = compbuff[2];

    pinlevelB = PORTB_MASK;     // set all port pins high
  }
  // clear port pin on compare match (executed on next interrupt)
  if(compare[0] == softcount) RED_CLEAR;
  if(compare[1] == softcount) GREEN_CLEAR;
  if(compare[2] == softcount) BLUE_CLEAR;
}

fungus


Hi everyone, I found the following code here https://gist.github.com/funkfinger/954874 (It's for ATTiny85 3 channel software PWM to drive RGB LED)
I tried it in the ATtiny85. It works. :)  But I want to add a sensor through the analogRead, Unfortunately it isn't WORK. =( Whether the sofeware PWM and analogread not be used simultaneously?
Could someone can help me to give some advice? Thanks.

Code: [Select]

#define RED PB0
#define GREEN PB1
#define BLUE PB2
#define LED_PORT PORTB
#define LED_DDR DDRB

#define SENSOR_PIN 2



Pin 2 is used for an LED, you can't use it for SENSOR_PIN.

Advanced Arduino

merrywhale

fungus, thanks for your reply. How can I get a analog input for the sensor?

Coding Badly

It's for ATTiny85 3 channel software PWM to drive RGB LED


Why would you use something like that?  The ATtiny85 processor is capable of generating three PWM signals without any special library.

dc42

You are using PB0,1,2 for your LED. ADC0 is shared with the reset pin, which you probably want to keep as reset so you can program via ICSP. ADC1 is shared with the PB2 pin. So that leaves ADC2 and ADC3 free for your sensor, assuming you are using the internal clock.

However, if you connect RED to PB4 instead, then you will have hardware PWM on all 3 LED pins, You can then use ADC1 for the sensor.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

merrywhale

I plan to make a light with three rgb fade and thermistor control. This 3 rgb not just blink and it must smoothly fades from red to green to blue. But Attiny85 only have 2 PWM. That's why I need 3 software PWM and an analog input for the thermistor. :~

dc42


But Attiny85 only have 2 PWM. That's why I need 3 software PWM and an analog input for the thermistor. :~


No, the ATtiny 25/45/85 have four independent timer/counter registers (OC0A, OC0B, OC1A, OC1B) that can be used for PWM. However, OC0B and OC1A share the same pin, so in practice you can have 3 PWM pins.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

merrywhale

Thanks dc42, Based on your reply I can used pin0, pin1 and pin4 for PWM, And pin2 for analog input. But the pin4 can't used analogWrite(4,0-255).

dc42


Thanks dc42, Based on your reply I can used pin0, pin1 and pin4 for PWM, And pin2 for analog input. But the pin4 can't used analogWrite(4,0-255).


Which Arduino core for the ATtiny are you using?
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

merrywhale

Thank for your guidance. It seems to works fine. Here is my code :

Code: [Select]
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define F_CPU 8000000

#define THERMISTOR_PIN 1

uint8_t r=0, g=0, b=0;

int brightness = 0;   
int fadeAmount = 1;

void setup()
{
    pinMode(THERMISTOR_PIN, INPUT);
}

void loop()
{
       
    DDRB = 1<<DDB4 | 1<<DDB1 | 1<<DDB0;
    TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00;   
    TCCR0B = 0<<WGM02 | 1<<CS00;
    TCCR1 = 0<<PWM1A | 0<<COM1A0 | 1<<CS10;
    GTCCR = 1<<PWM1B | 2<<COM1B0;
   
    for (;;)
    {
        int const rawVal = analogRead( THERMISTOR_PIN );
        brightness = brightness + fadeAmount;
 
        if (brightness == 0 || brightness == 255)
          fadeAmount = -fadeAmount ;
       
        if (rawVal < 343) {
            OCR0A = 0;
            OCR0B = brightness;
            OCR1B = 0; }
        else if (rawVal >= 343 & rawVal <= 360) {
            OCR0A = 0;
            OCR0B = 0;
            OCR1B = brightness; }
        else if (rawVal > 360 & rawVal <= 400) {
            OCR0A = brightness;
            OCR0B = 0;
            OCR1B = 0; }
        else  {
            OCR0A = brightness;
            OCR0B = brightness;
            OCR1B = brightness; }

        delay(100);
    }
}

fungus


fungus, thanks for your reply. How can I get a analog input for the sensor?


Ummm.... use a different pin (one that isn't being used by a LED!)

Advanced Arduino

merrywhale

Oh, now I have a new problem.  =(  I want to monitor the value of the thermistor through SoftwareSerial.  It will render with garbled text like this "€€€€€€€€€€€". Am I doing something wrong? Or SoftwareSerial can not be used in Attiny85? If yes, how do I do?

Code: [Select]
#include <SoftwareSerial.h>

#define THERMISTOR_PIN 1  //Pin2

SoftwareSerial mySerial(0, 1); // RX, TX

void setup()                   
{
  pinMode( THERMISTOR_PIN, INPUT );
  mySerial.begin(9600);
  mySerial.println("Attiny85 Software serial");
}

void loop()                   
{
  int const rawVal = analogRead( THERMISTOR_PIN );
  mySerial.print("TEMP=");
  mySerial.print( rawVal);
  mySerial.println( " " );
  delay(100);
}

Coding Badly

Or SoftwareSerial can not be used in Attiny85?


SoftwareSerial will not work well for your application: three pins for PWM and one pin for analogRead means there is one pin remaining.  SoftwareSerial needs two.

This core... http://code.google.com/p/arduino-tiny/ ...has support for a write-only Serial.  Some details available here...
http://forum.arduino.cc/index.php?topic=8878.msg74431#msg74431

If you are using an Arduino as a programmer to upload to your ATtiny85 then I suggest using TinyISP /  TinyDebugKnockBang instead of Serial.

dc42


Or SoftwareSerial can not be used in Attiny85?


SoftwareSerial will not work well for your application: three pins for PWM and one pin for analogRead means there is one pin remaining.  SoftwareSerial needs two.

This core... http://code.google.com/p/arduino-tiny/ ...has support for a write-only Serial.  Some details available here...
http://forum.arduino.cc/index.php?topic=8878.msg74431#msg74431

If you are using an Arduino as a programmer to upload to your ATtiny85 then I suggest using TinyISP /  TinyDebugKnockBang instead of Serial.



The other problem with using SoftwareSerial on an ATtiny is that the clock needs to be accurate to within about 2%, which may not be the case when you are using the internal oscillator, unless you calibrate it using the OSCCAL register. This is another reason to use Knock-Bang or a self-clocking protocol instead of regular serial.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Go Up