Go Down

Topic: Code works on ATtiny84, but not ATtiny44A (Read 735 times) previous topic - next topic

skootles

Nov 19, 2012, 06:21 am Last Edit: Sep 05, 2014, 09:58 pm by skootles Reason: 1
The ATtiny44 and 84 are both pin-compatible, and as far as I know, just the same microcontroller but with different EEPROM and flash memory sizes.

However, for some reason, my code here for this Simon Says game (see bottom of post) only works on an ATtiny84, not an ATtiny44A. At first I thought it was a voltage issue. I'm only using 2 AA batteries, and I was using an ATtiny84V, which requires less voltage according to the datasheet. However, I tried it on a regular ATtiny84 (which should require the same amount of voltage an ATtiny44A does) and it worked just fine.

I'm kind of stumped on this one. Can anyone think of why the code won't work? I'm running them at 8MHz, internal oscillators. When I use the ATtiny84, everything works right - the startup sound plays, and then the light sequence flashes. When I use the ATtiny44A, no startup sound plays, no light sequence flashes. Here's a video of how it works with the ATtiny84:

http://www.youtube.com/watch?v=NAr4ls4hZMA&feature=g-crec-u


My code is here:

Code: [Select]
/*
Application Name: Simon Says Game Kit
Description: A simple game of Simon Says.
Author: Jeff Murchison
Contact: http://murchlabs.com/contact/
Date: November 15, 2012
Version: 1.0
License:

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
http://creativecommons.org/licenses/by-nc-sa/3.0/

To purchase a kit, please visit:
http://jeffmurchison.com/blog/simon-says-game-kit/

Notes:

This code uses cores from the arduino-tiny project, and is designed for use on an ATtiny84.
For more information and to download the cores, visit the arduino-tiny Google Code page:
http://code.google.com/p/arduino-tiny/

*/


#include <EEPROM.h>   // We're going to be writing some stuff to the microcontroller's EEPROM

int buzzerPin = 2;  // The buzzer pin
int buttonPin[] = {
 0, 7, 8, 9, 10}; // The four button input pins
int ledPin[] = {
 0, 3, 4, 5, 6};  // LED pins
int buzzerTone[] = {
 50, 200, 400, 600, 800};  // Buzzer Tones for the different buttons (fail, 1, 2, 3, 4)

int turnCount = 1;  // Turn counter
int buttonState = 0;  // Button state checker

const int maxTurns = 100; // The maximum number of random numbers that will be generated.
int randomArray[maxTurns]; // Array that will store the random numbers for the game
int inputArray[maxTurns];  // Array that will store user input

int eepromValue = 0;

boolean playedThisTurn = false;  // Boolean variable for if the sequence has been played already
boolean buttonPressed = false; // Boolean variable for f a button has been pressed



void setup()
{
 //Serial.begin(9600);  // Serial is commented out as the ATtiny doesn't support it. Useful for debugging on an ATmega328.

 pinMode(buzzerPin, OUTPUT);  // Set the buzzer to output

 for(int x=1; x <= 4; x++) {  // Set pinmodes for button, LED pins, set LEDs HIGH (off)
   pinMode(ledPin[x], OUTPUT);
   digitalWrite(ledPin[x], HIGH);
   pinMode(buttonPin[x], INPUT);
 }
 //Serial.print("---------");
 //Serial.println("");
 randomArrayGen();
 //Serial.print("Random Array Generated.");
}


void loop()
{
 eepromValue = EEPROM.read(0);
 if ((eepromValue + turnCount) >= 255) {   // EEPROM bytes can only hold a value from 0 to 255. This ensures we don't overflow.
   EEPROM.write(0, turnCount);
 }
 else {
   EEPROM.write(0, (turnCount + eepromValue)); // Add the turncount to EEPROM value 0. We use this for random seed.
 }
 if (playedThisTurn == false) {  // If the player hasn't pushed a button this turn yet, then..
   //Serial.println("");
   //Serial.println("");
   //Serial.print("Turn:");
   //Serial.print(turnCount);
   //Serial.println("");
   //Serial.println("Playing Array");
   //Serial.println("---------");
   playedThisTurn = true;  

   for (int x=1; x <= turnCount; x++) {  // Play all of the moves in the random array at the beginning of each turn
     LEDandTone(ledPin[randomArray[x]], buzzerTone[randomArray[x]]);
     //Serial.println(randomArray[x]);
   }
   //Serial.println("---------");
 }

 for (int z=1; z <= turnCount; z++){
   //Serial.println("");
   //Serial.println("");
   //Serial.print("inputNumber: ");
   //Serial.print(z);
   buttonCheck(z);
   buttonPressed = false;
 }
 turnCount++;
 delay(500);
}


void randomArrayGen ()  // Function for generating the random array
{
 randomSeed(EEPROM.read(0));
 for (int x=1; x < maxTurns; x++) {
   randomArray[x] = random(1, 5);
   //Serial.println(randomArray[x]);
 }
 for (int t=600; t <= 1000; t=t+7){
   tone(buzzerPin, t);
   delay(20);
   noTone(buzzerPin);
   delay(10);
 }
 delay(500);
}

void LEDandTone(int ledPin2, int buzzerTone2)
{
 tone(buzzerPin, buzzerTone2);  
 digitalWrite(ledPin2, LOW);
 delay(400);
 digitalWrite(ledPin2, HIGH);
 noTone(buzzerPin);
 delay(100);
}


void buttonCheck(int inputNumber)  //Function for allowing user input and checking input against the generated array
{
 while (buttonPressed == false){  // As long as a button has not been pressed this turn, keep checking button inputs
   for(int y=1; y <= 4; y++) {
     buttonState = digitalRead(buttonPin[y]);
     if (buttonState == HIGH) { //Checking for button push

       //Serial.println("");
       //Serial.print("Button Pressed: ");
       //Serial.print(y);
       //Serial.println("");

       LEDandTone(ledPin[y], buzzerTone[y]);
       inputArray[inputNumber] = y;

       playedThisTurn = false;
       buttonPressed = true;
       y = 5;

       if (inputArray[inputNumber] == randomArray[inputNumber]) { //Checks value input by user and checks it against
         //Serial.print("CORRECT!");
         //Serial.println("");                
       }                                    
       else {
         //Serial.print("INCORRECT");
         //Serial.println("");
         //Serial.println("");
         //Serial.println("------- DEBUG INFO -------");
         //Serial.println("");
         //Serial.print("inputArray[inputNumber]: ");
         //Serial.print(inputArray[inputNumber]);
         //Serial.println("");
         //Serial.print("randomArray[inputNumber]: ");
         //Serial.print(randomArray[inputNumber]);
         //Serial.println("");
         //Serial.print("[inputNumber]: ");
         //Serial.print(inputNumber);
         //Serial.println("");
         //Serial.print("turnCount: ");
         //Serial.print(turnCount);
         //Serial.println("");
         fail();  
       }
     }
     /*if (buttonPressed == true){
      Serial.println("Exiting buttonState loop.");
      }*/
   }
   /*if (buttonPressed == true){
    //Serial.println("Exiting for loop.");
    }*/
 }
 //Serial.print("Exiting while loop, inputNumber should increment after this");
 delay(200);
}


void fail()  //Function used if the player fails to match the sequence
{
 tone(buzzerPin, 50);
 for (int x=1; x <= 4; x++){
   digitalWrite(ledPin[x], LOW);
 }
 delay(2000);
 //EEPROM.write(0, turnCount+(EEPROM.read(0)));
 turnCount = 1; //Resets turn value so the game starts over without need for a reset button
 for (int x=1; x <= 4; x++){
   digitalWrite(ledPin[x], HIGH);
 }
 noTone(buzzerPin);
 delay(1500);
 randomArrayGen();
}

Coding Badly

Code: [Select]
const int maxTurns = 100; // The maximum number of random numbers that will be generated.
int randomArray[maxTurns]; // Array that will store the random numbers for the game
int inputArray[maxTurns];  // Array that will store user input


...alone is 400 bytes of memory.  How much SRAM does the ATtiny44 have?

Can the arrays be changed to an eight bit data type?

Nick Gammon

I was about to say that. It has 256 bytes of RAM.

Nick Gammon


... just the same microcontroller but with different EEPROM and flash memory sizes.


And RAM sizes *cough*.

guix

#4
Nov 19, 2012, 07:02 am Last Edit: Nov 19, 2012, 07:05 am by guix Reason: 1
Like it has been said, not enough RAM available...Most of your variables can be changed to byte instead of int. Also I noticed, that you constantly write to eeprom in loop(), considering the eeprom have a life of only 100.000 write/erase operations, I think it's a bad idea!

You can use the Arduino Enhanced IDE and it will report a warning if you use too much memory :)

skootles

Thanks for the quick replies, everyone. I don't know how I missed that. I temporarily brought the arrays down to 50 instead of 100 and sure enough, it works fine now that it's not using as much memory.


Code: [Select]
const int maxTurns = 100; // The maximum number of random numbers that will be generated.
int randomArray[maxTurns]; // Array that will store the random numbers for the game
int inputArray[maxTurns];  // Array that will store user input


...alone is 400 bytes of memory.  How much SRAM does the ATtiny44 have?

Can the arrays be changed to an eight bit data type?


Well, I'm not sure to be honest. My technical knowledge of the different data types and their memory footprints is fairly basic. Would it be as simple as changing the 'int' to 'byte', or is it more complicated than that?


Like it has been said, not enough RAM available...Most of your variables can be changed to byte instead of int. Also I noticed, that you constantly write to eeprom in loop(), considering the eeprom have a life of only 100.000 write/erase operations, I think it's a bad idea!

You can use the Arduino Enhanced IDE and it will report a warning if you use too much memory :)

Yeah, I started using the EEPROM to get a better random seed. I guess my analog pins were grounded too well on my PCB, because I wasn't getting anything by using them. Basically it just keeps track of how far into the sequence the user gets, then adds that to the value already in the EEPROM. This creates a somewhat random number that I can use for a seed. Another user suggested an even better way using a timer, so I may try that out as well. I was aware of the 100,000 operations limit, but I don't think most people would actually hit that limit. People might get, max, 15-20 turns in before failing, so it'd take 5000-6500 games played to exhaust the limit. Still, I might go with the timer solution just in case.

Nick Gammon

Quote
Code: [Select]
for (int x=1; x < maxTurns; x++) {
   randomArray[x] = random(1, 5);
   //Serial.println(randomArray[x]);
 }


Since you seem to be storing a number from 1 to 4 then a byte array should be plenty. That would take you up to 255.

Coding Badly


Go Up