Go Down

Topic: ATtiny85 with SoftwareSerial and PinChange interrupts (Read 112 times) previous topic - next topic

sancho_sk

Hi all.
I am working on a project with ATtiny85.
The chip is checking multiple pins for pin change.
Within the code for ISR(PCINT0_vect) I am reading the port status and finding out what to do based on which pin actually changed.
This works OK.
Now I need to add debug function with SoftwareSerial.
The problem here is that it uses its own handler for ISR(PCINT0_vect).
As the tiny has no other interrupts, I have a problem.
What I did is I edited the library (renamed it to SoftwareSerialInt.h+cpp) and removed the actual code that sets the interrupt.
The idea here is to add additional if-then statement to my original handler and in case the pin for SoftwareSerial changed, call it's handle_interrupt() function.
And this is the problem.
I made a code like this:
Code: [Select]

SoftwareSerialInt SerialI(M1, M2);
...
#if defined(PCINT0_vect)
ISR(PCINT0_vect)
{
  if (SerialI.isListening())
  {
    SerialI.handle_interrupt();
  } else {
    // my own interrupt here
  }
}
#endif

But the compiler complains
Code: [Select]
attiny85.ino:121: undefined reference to `SoftwareSerialInt::handle_interrupt()'
collect2: error: ld returned 1 exit status
Error compiling.

This clearly states that the class did not publicly announced the handle_interrupt function.
However, when reading the .h file, I can see:
Code: [Select]
class SoftwareSeriapInt : public Stream
...
public:
...
// public only for easy access by interrupt handlers
  static inline void handle_interrupt();

I have no idea what am I doing wrong. Can someone, please, point me out to some information how can I actually do the decision before calling the library?
Thanks!

DrAzzy

Here's another approach:

Use my ATTiny core. It has a built-in software serial named Serial (like the real serial on boards that have hardware serial) that uses the analog comparator interrupt, not a PCINT). TX is AIN0 (pin 0), RX is AIN1 (pin 1). Then use "Serial" instead of creating a software serial instance, and you can use PCINT''s freely.

https://github.com/SpenceKonde/ATTinyCore (can be installed manually, or using the board manager json url in my sig)
ATtiny core for 841+1634+828 and x313/x4/x5/x61/x7/x8 series Board Manager:
http://drazzy.com/package_drazzy.com_index.json
ATtiny breakouts (some assembled), mosfets and awesome prototyping board in my store http://tindie.com/stores/DrAzzy

sancho_sk

Cool idea. However the pins 0 and 1 are also the only ones I can use for PWM :(
Have to read if I can use other pins for PWM, too...

DrAzzy

Cool idea. However the pins 0 and 1 are also the only ones I can use for PWM :(
Have to read if I can use other pins for PWM, too...
My core gives you one more PWM pin, on pin 3 I think (unfortunately, those are the only three pins we can get PWM out of :-/ ). ATTiny85 cores that only have two PWM outputs are pretty widespread - timer1 on the '85 *is* kinda strange.
ATtiny core for 841+1634+828 and x313/x4/x5/x61/x7/x8 series Board Manager:
http://drazzy.com/package_drazzy.com_index.json
ATtiny breakouts (some assembled), mosfets and awesome prototyping board in my store http://tindie.com/stores/DrAzzy

sancho_sk

Perhaps I can live with 1 PWM only for driving the motor correctly - I have to test it using 328 and then get back to Tiny85...

sancho_sk

YES!
It works with single PWM!!!

I just had to slightly modify the original dual-PWM code from
Code: [Select]
void pwmOut(int out) {
  if (out < 0) {
    analogWrite(M1, 0);
    analogWrite(M2, abs(out));
  }
  else {
    analogWrite(M1, abs(out));
    analogWrite(M2, 0);
  }
}

to
Code: [Select]
void pwmOut(int out) {
  out = out * moveCoef;
  if (out < 0) {
    digitalWrite(M1, 0);
    analogWrite(M2, abs(out));
  }
  else {
    digitalWrite(M1, 1);
    analogWrite(M2, 255 - abs(out));
  }
}

So, now I have to learn how to use the PWM on PB4 correctly and set the maximum frequency and I am good to go :)
Thanks for now - seems like I'll have a long night ahead of me :)

DrAzzy

Nice! Glad it's working - yeah, timer1's a little weird, doesn't work quite like other timers. You can, for example, change the prescaler to any factor of two instead of every-few-powers-of-2 like most AVR timers, and you can clock it off the PLL if you need it running at higher speed.
ATtiny core for 841+1634+828 and x313/x4/x5/x61/x7/x8 series Board Manager:
http://drazzy.com/package_drazzy.com_index.json
ATtiny breakouts (some assembled), mosfets and awesome prototyping board in my store http://tindie.com/stores/DrAzzy

sancho_sk

Nice! Glad it's working - yeah, timer1's a little weird, doesn't work quite like other timers.
Well, I have another problem.
After days of trial-and-error, I'm stuck.
I made a simple code like this:
Code: [Select]
/*
 * Goal: Have DC motor with encoder
 * driven by ATtiny85 and Step and Direction
 * from RAMPS
 * However, when starting, I want to determine a "DEBUG"
 * condition and wnable serial port to set PID and parameters
 * like enable (minimum and maximum search.
 *
 * Tiny setup:
 * 1 - PB5 - Encoder A
 * 2 - PB3 - Encoder B
 * 3 - PB4 - DC PWM
 * 4 - GND
 * 5 - PB0 - Step / Serial RX
 * 6 - PB1 - Direction / Serial TX
 * 7 - PB2 - DC direction
 * 8 - VCC
 */

// first - test the PB4 PWM direction pins
#define M1  4
#define M2  2

void setup() {
  // PWM setup according
  // http://matt16060936.blogspot.ch/2012/04/attiny-pwm.html
  DDRB |= 1<<DDB4;  // set the PB4 as output
  DDRB |= 1<<DDB2;  // set the PB2 as output (direction pin)
  TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00;
          // set the timers COM0A0 for enabling
          // timers and the rest for timer B
          // without COM0A0 the Timer1 will not work
  TCCR1 = 0<<PWM1A | 0<<COM1A0 | 1<<CS10;
          // this tells not to use pins OC0B and OC1A
          // and use no prescaler
  GTCCR = 1<<PWM1B | 2<<COM1B0;
          // enable OC1B (PB4)
          // and clears it to bottom
  // I'll use OCR1B = x to set the PWM value

  Serial.begin(115200);
  Serial.println("Setup is over");
}

void loop() {
  for (int i = 0; i < 256; i++) {
    OCR1B = i;
    delay(10);
    }
  Serial.println("Loop over, restarting");
}

The problem here is - if I don't setup the PWM for PB4, the serial works OK.
If I do set it up, the PWM works OK, but the serial does not :(
I suspect that by messing with the PWM I've set something wrong for the analogue comparator, I just have no idea what :(
Can someone, please, assist?

sancho_sk

Stupid me - simple typo :(
Instead of setting the COM0A0 I've erased it :(
By changing the line from
Code: [Select]
 TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00;
to
Code: [Select]
 TCCR0A = 1<<COM0A0 | 2<<COM0B0 | 3<<WGM00;
It works.
I've spent 3 nights on this :(

sancho_sk

Well, thanks for the suggestion, but this finally does not work.
The problem here is the codespace - when I include the serial processing routines, I run out of the 8kB available.
:(

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy