Arduino Code to ATtiny84 microcontroler: do I have the right pins?

To whom it may concern:

I'll start with a little detail of the system. I am working on using an RFID system to read in an RFID tag and then move a motor if the tag is the same as a stored tag. I can run the system using an Arduino Uno with the following code:

#include <SoftwareSerial.h>

SoftwareSerial gtSerial(0, 1);

//Variables
  const int serialPin = 0;
  const int pinRFID = 8;
  const int pinL = 10;
  const int pinU = 9;
  const int locked = 0;
  const int unlocked = 1;
  char tag1[12];  
  char incomingByte = 1;
  int index = 0;
  int sts = 1; //this is the status of the mechansim. 0 = locked, 1 = unlocked

void setup() {
  pinMode(pinRFID, OUTPUT);
  pinMode(serialPin, INPUT);

  Serial.begin(2400);
  gtSerial.begin(2400);
  //set up tags;
  tag1[0] = '\n'; //line feed
  tag1[1] = '4';
  tag1[2] = '6';
  tag1[3] = '0';
  tag1[4] = '0';
  tag1[5] = '3';
  tag1[6] = '8';
  tag1[7] = '9';
  tag1[8] = '8';
  tag1[9] = 'E';
  tag1[10] = '5';
  tag1[11] = '\r'; //carriage return
  lock();
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(pinRFID, LOW);
  delay(500);
  index = 0;
  if(gtSerial.available()==0){
    lock();
  }
  if (gtSerial.available()>0){
     while(index < 12) {
      //read incoming byte:
      incomingByte = gtSerial.read();
      //print it
      Serial.print("Position ");
      Serial.print(index);
      Serial.print(" is: ");
      Serial.print(incomingByte);
      Serial.print('\n');
      delay(10);
      if(incomingByte != tag1[index]){
        lock();
        break;
      }
      if(index == 11){
        unlock();
      }
      index++;
     }
    delay(500);
  }
  Serial.print('\n');
  Serial.print("I'm done");
  Serial.print('\n');
  digitalWrite(pinRFID, HIGH);
  delay(500);
}

//Additional functions
void lock(){
  //lock the gun if not already locked
  Serial.print("Hit lock function");
  Serial.print('\n');
  if(sts == locked){
    Serial.print("I'm already locked.");
    Serial.print('\n');
    return;
  }
  else if(sts == unlocked){
    //lcok
    Serial.print("Did the locking.");
    Serial.print('\n');
    analogWrite(pinL, 255); //set pin L to 5V (high)
    analogWrite(pinU, 0); //set pin U to 0V (low)
    delay(1000);
    analogWrite(pinL, 0);
    sts = locked;
    return;
  }
}

void unlock(){
  //unlock the gun if not already unlocked
  Serial.print("Hit unlock function");
  Serial.print('\n');
  if(sts == unlocked){
    Serial.print("Already unlocked.");
    Serial.print('\n');
    return;
  }
  else if(sts == locked){
    //unlock
    Serial.print("Did the unlocking.");
    Serial.print('\n');
    analogWrite(pinU, 255); //set pin U to 5V (high)
    analogWrite(pinL, 0); //set pin L to 0V (low)
    delay(1000);
    analogWrite(pinU, 0);
    sts = unlocked;
    return;
  }
}

However, the system is such that I want to program the code to an ATtiny84 microcontroler (due to size limitations). I have seen (and followed) the directions on sites such as the following to send the code to the microcontroler:

The problem that I have is that I cannot get the microcontroler to run with the code. Here is the code that I tried to use with the microcontroler:

#include <SoftwareSerial.h>


//Variables
  const int serialPin = 6;
  const int pinRFID = 5;
  const int pinL = 7;
  const int pinU = 8;
  const int locked = 0;
  const int unlocked = 1;
  char tag1[12];  
  char incomingByte = 1;
  int index = 0;
  int sts = 1; //this is the status of the mechansim. 0 = locked, 1 = unlocked
SoftwareSerial gtSerial(serialPin, 1);

void setup() {
  pinMode(pinRFID, OUTPUT);
  pinMode(serialPin, INPUT);

  Serial.begin(2400);
  gtSerial.begin(2400);
  //set up tags;
  tag1[0] = '\n'; //line feed
  tag1[1] = '4';
  tag1[2] = '6';
  tag1[3] = '0';
  tag1[4] = '0';
  tag1[5] = '3';
  tag1[6] = '8';
  tag1[7] = '9';
  tag1[8] = '8';
  tag1[9] = 'E';
  tag1[10] = '5';
  tag1[11] = '\r'; //carriage return
  lock();
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(pinRFID, LOW);
  delay(500);
  index = 0;
  if(gtSerial.available()==0){
    lock();
  }
  if (gtSerial.available()>0){
     while(index < 12) {
      //read incoming byte:
      incomingByte = gtSerial.read();
      //print it
      Serial.print("Position ");
      Serial.print(index);
      Serial.print(" is: ");
      Serial.print(incomingByte);
      Serial.print('\n');
      delay(10);
      if(incomingByte != tag1[index]){
        lock();
        break;
      }
      if(index == 11){
        unlock();
      }
      index++;
     }
    delay(500);
  }
  Serial.print('\n');
  Serial.print("I'm done");
  Serial.print('\n');
  digitalWrite(pinRFID, HIGH);
  delay(500);
}

//Additional functions
void lock(){
  //lock the gun if not already locked
  Serial.print("Hit lock function");
  Serial.print('\n');
  if(sts == locked){
    Serial.print("I'm already locked.");
    Serial.print('\n');
    return;
  }
  else if(sts == unlocked){
    //lcok
    Serial.print("Did the locking.");
    Serial.print('\n');
    analogWrite(pinL, 255); //set pin L to 5V (high)
    analogWrite(pinU, 0); //set pin U to 0V (low)
    delay(1000);
    analogWrite(pinL, 0);
    sts = locked;
    return;
  }
}

void unlock(){
  //unlock the gun if not already unlocked
  Serial.print("Hit unlock function");
  Serial.print('\n');
  if(sts == unlocked){
    Serial.print("Already unlocked.");
    Serial.print('\n');
    return;
  }
  else if(sts == locked){
    //unlock
    Serial.print("Did the unlocking.");
    Serial.print('\n');
    analogWrite(pinU, 255); //set pin U to 5V (high)
    analogWrite(pinL, 0); //set pin L to 0V (low)
    delay(1000);
    analogWrite(pinU, 0);
    sts = unlocked;
    return;
  }
}

As far as I know, the only real difference between the two codes is the pins that I am calling in the functions. This brings me to the question that I have: am I calling the correct pins? or am I fundamentally trying to use the ATtiny84 for something that it can't do?

I don't know if this will be super helpful, but here is the data sheet for the ATtiny84:

Please let me know if there is anything I can do to help with the process of debugging.

Thanks,
Zachary Biegler

What core are you using?

The ATTiny84 does not have any hardware serial. So the Serial instance you're using is a built-in software serial (this is a feature offered on some cores, including the one I maintain).

That means that only one of those serials can send or receive at a time, otherwise you'll get/send garbage - they are both software serial.

I recommend using an ATTiny841 for your application, since you want it small and need to communicate with two devices over serial - it comes equipped with two hardware serial ports (Serial and Serial1 ) which work like normal serial ports (can receive while sending, and don't interfere with eachother), and is otherwise compatible with the ATtiny84 - it's supported by my ATtiny Core ( GitHub - SpenceKonde/ATTinyCore: Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8 or board manager URL in my sig), and I sell basic breakout boards too.

Sorry Doc for adding to your post, but I would like to suggest a possible solution to the OP, ignoring the issue with two software serials.

Look up the pins numbers that work for the Arduino and identify the ports they are on.
Then match those ports with the tiny's ports and connect the same way.

As an example, pin 13 on Arduino is on port B5 (I think). If your tiny has PB5 then you can use 13 in your code. If not, find the ports that the tiny has and find their corresponding pins onthe Uno and use them in your sketch.
It may still fail, but it's worth a shot if you don't want a core for tiny.
pins_arduino.h for the Uno can also help with this trick.

Hey guys,

Thanks for your replies. I apologize that I am slow to respond, I had thought I would get an email notification when there was a reply, unfortunately that is not the case.

I don't understand what you mean by core, could you clarify?

As far as I know, I only need one serial port in this system. I only need to receive serial data from the RFID board. The serial out should only be on the code that I use when the system is interfaced with the computer (so that I can make sure that the code is running smoothly).

So, according to the data sheet from Atmel, PA6 is the serial data input for the ATtiny84 (section 19.5, page 163). The question that I am really finding that I have is this: how do I tell the code which pins to use? I know that physical pin 1 doesn't necessarily correspond to pin 1 as far as the coding is concerned. So, if I want to use PA6 (physical pin 7), do I call it pin 6? Or do I call it pin 7? Or something else?

I have attached the pinout that we referenced for the naming of our pins in the code.

Thank you so much for your help,

Zachary Biegler

I don't understand what you mean by core, could you clarify?

The "core" refers to the files you download and install to be able to program the tiny.
In your case (if you followed the instructable you linked to) it is these files :

Google Code Archive - Long-term storage for Google Code Project Hosting. *1

If you look in the file called pins_arduino.c you will find this mapping of the pins:

// ATMEL ATTINY84 / ARDUINO
//
//                           +-\/-+
//                     VCC  1|    |14  GND
//             (D  0)  PB0  2|    |13  AREF (D 10)
//             (D  1)  PB1  3|    |12  PA1  (D  9) 
//                     PB3  4|    |11  PA2  (D  8) 
//  PWM  INT0  (D  2)  PB2  5|    |10  PA3  (D  7) 
//  PWM        (D  3)  PA7  6|    |9   PA4  (D  6) 
//  PWM        (D  4)  PA6  7|    |8   PA5  (D  5)        PWM
//                           +----+

Following this:

digital.write(10,HIGH);

will set physical pin 13 high.

*1) these files have been moved to arduino-tiny

There are also two pinouts used, depending on the core you're using - My core ( GitHub - SpenceKonde/ATTinyCore: Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8 or http://drazzy.com/package_drazzy.com_index.json via board manager ) lets you choose which one you want from the tools menu when 'x4 is selected, for other cores, consult the documentation that came with the core.

The ATTiny84 does not have a serial port - section 19.5 describes the pins used for ICSP (in circuit serial programming, which is like SPI - NOT like serial. "Serial" is colloquially used to refer to a UART (that's what you're using when you do Serial.print and such) - but strictly speaking, it refers to any protocol in which data is transferred one bit at a time. So you need to look more carefully whenever serial is mentioned SPI and ICSP(aka ISP) programming uses a clock, and two data lines. Serial uses TX and RX)

I suspect you are using the wrong pins for the Serial (built-in software serial provided by the core you're using) - consult the documentation for the core to identify which pins. I think it's the same as mine, the analog comparator pins.

But in any event, there is no hope for this:

if (gtSerial.available()>0){
     while(index < 12) {
      //read incoming byte:
      incomingByte = gtSerial.read();
      //print it
      Serial.print("Position ");
      Serial.print(index);

UNLIKE ARDUINOs WITH A HARDWARE SERIAL PORT, here BOTH of those are software implementations.
You are receiving and sending data at the same time, because you don't do anything to ensure that no more data is coming in before printing what you have. So imagine getting a two byte string... it gets the first byte, that condition is met, and your code starts printing - while the second byte is still coming in. And you're trying to read one while printing to the other. That will result in gibberish on both! You need to ensure that you don't send any data while receiving, and don't receive any data while sending - or use a part with at least one hardware serial port. Such as the attiny841 (which has 2, and is otherwise very similar to the 84). I do sell attiny841 boards, assembled, with the pins marked (with the pin mapping used in my core, linked above)

Hey guys,

Thanks again for the responses. As far as the core, if I am understanding correctly what you are asking for, I downloaded the ATTinyCore - Master. I hope that is what you are looking for.

As far as the serial stuff, is it possible for me to still get in serial data and just not print anything out? I was using the Serial.print simply as a means of making sure that the code was working while it was attached to the Arduino and I don't need the system to output any serial data. According to the datasheet, PA6 is the USI input (three wire mode). Would a USI pin work for reading in serial data? Or does it compare more to ISP rather than UART?

Maybe I am reading the datasheet wrong, but in 14.4.1 on page 124 it says that one may use the USI data register in three wire mode for a "more compact and higher performance UART rather than by software, only." My understanding is that this means that I should be able to use pin PA6 to read in serial data. Am I correct?

I do really appreciate all of your guys help.

Thanks,
Zachary Biegler