3 digit 7 segment display works on UNO but displaying jibberish using ATTiny2313

We are trying to get the following code to work on a ATTiny2313. As mentioned, it works on an UNO. This project is high volume and price sensitive, so a display chip is not going to be within budget. Thank you !

/* 3 digit 7 segments LED count up

  Display 3 digit 7 segment LED and count up perpetual
  to demonstrate multiplexing of LED in software.

  Further explanation in
  https://kositapan.wordpress.com/2014/03/01/multiplexing-4-digit-led-with-arduino
 */

const int ledPin =  13;     // blink onboard LED to test multi tasking
const int nbrDigits = 3;    // this is 3 digit LED
//  mapping segment DP,G,F,E,D,C,B,A  data pin
const int segmentPins[8]         = { 7,6,5,4,3,2,1,0 };
//  mapping digit 1,2,3  data pin, skip pin 13 on board LED
const int digitPins[nbrDigits]   = { 8,9,10 };

//  7 segment pattern from 0-9, last bit is DP - don't use
const byte numeral[10] = { //ABCDEFG /dp
  B11111100, // 0
  B01100000, // 1
  B11011010, // 2
  B11110010, // 3
  B01100110, // 4
  B10110110, // 5
  B10111110, // 6
  B11100000, // 7
  B11111110, // 8
  B11110110, // 9
};

//  internal buffer of digit 1,2,3 initial is 10 (blank)
static int valueDigit[nbrDigits] = { 10, 10, 10,};
int ledState = LOW;             // onboard LED blink state

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
const long interval         = 1000;    // interval to blink onboard LED (milliseconds)
const long intervalCountUp  = 200;     // 100 interval to count up number (milliseconds)
unsigned long lastCountUpMillis  = millis();
unsigned long lastBlinkMillis    = millis();

static int currentNumber         = 000;    // arbitary initial LED number

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);   
  for (int i=0; i<8; i++)
    pinMode(segmentPins[i], OUTPUT);
  for (int i=0; i<nbrDigits; i++)
    pinMode(digitPins[i], OUTPUT);
//  Serial.begin(9600);
}

// ShowDigit:  physical display one digit of LED
// This function should be optimized since it is called all the time
void showDigit(int number, int digit) {
  boolean  isBitSet;

  // turn off all digit before write anything
  // to minimize flicker
  for (int i=0; i<nbrDigits; i++)
    digitalWrite(digitPins[i], LOW);

  // write segment bit accordingly
  for (int segment=0; segment<8; segment++) {
    if (number<0||number>9)
      isBitSet = 0;
    else
      isBitSet = bitRead(numeral[number], segment);
    digitalWrite(segmentPins[segment], isBitSet);
  }

  // now turn on particular digit
  digitalWrite(digitPins[digit], HIGH); 
}

//  refreshLED: main dispatch for LED multi digit multiplexing
//              this version just serialize each digit display
//  future version should optimize delay execution until each digit has
//              display time of 100Hz to minimize CPU usage
void refreshLED() {
  static int lastDigit = 0;
  if (++lastDigit > nbrDigits)
    lastDigit = 0;
  showDigit(valueDigit[lastDigit], lastDigit);
}

//  showDecimal   convert decimal and stored result in LED buffer format
//                this function do not display anything
//                the refreshLED will actually display LED buffer
void showDecimal(int number) {
  // negative mean blank all digit
  if (number<0) {     for (int d=(nbrDigits-1); d>=0; d--) {
      valueDigit[d] = 10;    // 10 is interpret as blank digit
    }
    return;
  }
  for (int d=(nbrDigits-1); d>=0; d--) {
    if (number > 0) {
      valueDigit[d]  = number%10;
      number         = number / 10;
    }
    else valueDigit[d] = 10;
  }
}

void loop()
{
  unsigned long now                = millis();

  // here is where you'd put code that needs to be running all the time.
  refreshLED();

  // check to see if it's time to count up 7 segment LED
  if (now - lastCountUpMillis > intervalCountUp) {
    currentNumber++;
    showDecimal(currentNumber);
    lastCountUpMillis += intervalCountUp;
  }

  // check to see if it's time to blink onboard LED
  if (now - lastBlinkMillis > interval) {
    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
    lastBlinkMillis += interval;
  }
}

hahobson:
This project is high volume and price sensitive, so a display chip is not going to be within budget.

I simply cannot believe you cannot afford US$1.79!

Between 1000 and 10000 pcs, believe it

Schematic please. We need to see how the display is wired, which segments to which pins, series resistors, transistors etc/

How are you uploading sketch to the tiny?

For something that is price sensitive and needed to run on a ATtiny you're pissing away memory as if it's a Intel i7...

And the biggest question, because the Uno and the ATTiny2313 are not pin compatible, how did you wire it?

Please find the schematic bowl. As to how Arduino is loaded and how the ATTiny2313 is programmed, hope to let you know soon. Thanks!

Too blurred, can't read it. Post a higher resolution version please.

Sorry, will do

What I think I can see raises some questions:

  • You seem to be using a 16-port i2c expander with the tiny. Would it not have been lower cost to use an atmega1284?
  • You seem to have common ground on the input side and the output side of your opto-isolators. Does that not defeat the object of having them?
  • Do you really need a crystal for this application? Wouldn't the internal oscillator @8MHz be fast enough?

Because you are unwilling to use any extra display driving chip like MAX7219 or similar, you may build the following 3-digit cc-type multiplexed display unit. The driving software is a straight forward routine.

GolamMostafa:
Because you are unwilling to use any extra display driving chip like MAX7219 or similar, you may build the following 3-digit cc-type multiplexed display unit. The driving software is a straight forward routine.

@GolamMostafa, well done, as helpful as always.

How to Program ATtiny2313
How to program ATTiny2313

Attiny2313_MCP.pdf (19.6 KB)

PaulRB:
What I think I can see raises some questions:

  • You seem to be using a 16-port i2c expander with the tiny. Would it not have been lower cost to use an atmega1284?

  • You seem to have common ground on the input side and the output side of your opto-isolators. Does that not defeat the object of having them?

  • Do you really need a crystal for this application? Wouldn't the internal oscillator @8MHz be fast enough?

Thanks for your input. We will see of the Atmega1284 is cost effective. I think 8MHz is fast enough, so I will ask why is a crystal is needed. I will ask about the common ground

[/list]

And now you posted a schematic that is sharp but is also clearly different from your other post...

I think you need to make a debug setup, ONLY the ATtiny and the dusplay + resistors and make a testrun.

septillion:
And now you posted a schematic that is sharp but is also clearly different from your other post...

There is a new schematic? Where? Was a post deleted?

The PDF in reply #11

Ah, sorry, I missed that!

It won't open on my phone. Will try on pc later.

http://codeandlife.com/2012/02/24/7-segment-multiplexing-with-uln2003-pnp-transistors/

Wondering if this code could be helpful

Your original code is good. It worked on the Uno. You just have the wiring wrong because the pins are different on the attiny.

Use this diagram to help you check. Its the blue Arduino pin numbers that you need to get right in your sketch.

Compare them to the pin numbers on these lines:

//  mapping segment DP,G,F,E,D,C,B,A  data pin
const int segmentPins[8]         = { 7,6,5,4,3,2,1,0 };
//  mapping digit 1,2,3  data pin, skip pin 13 on board LED
const int digitPins[nbrDigits]   = { 8,9,10 };

If they don't match up, either change the numbers in the arrays, or change the physical wiring to match.

PaulRB:
Your original code is good. It worked on the Uno. You just have the wiring wrong because the pins are different on the attiny.

Use this diagram to help you check. Its the blue Arduino pin numbers that you need to get right in your sketch.

Compare them to the pin numbers on these lines:

//  mapping segment DP,G,F,E,D,C,B,A  data pin

const int segmentPins[8]        = { 7,6,5,4,3,2,1,0 };
//  mapping digit 1,2,3  data pin, skip pin 13 on board LED
const int digitPins[nbrDigits]  = { 8,9,10 };




If they don't match up, either change the numbers in the arrays, or change the physical wiring to match.

Thank you ! I will look into it and report back.