ATtiny85 12 led VU Meter

xplp
Offline
Зарегистрирован: 21.12.2012

hi all

Решил оставить это тут, вдруг кому нибудь пригодится (=





const int numLed[12][4] = {
          {0,1,2,4}, //1
          {0,1,4,2}, //2
          {0,2,4,1}, //3
          {1,0,2,4}, //4
          {1,0,4,2}, //5
          {1,2,4,0}, //6
          {2,1,0,4}, //7
          {2,0,4,1}, //8
          {2,4,1,0}, //9
          {4,0,1,2}, //10
          {4,0,2,1}, //11
          {4,2,1,0}, //12
}; 

int g = 11;
int h = 0;
int k = 0;
 
void setup() {                
  
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, INPUT);
  pinMode(4, OUTPUT);
  
}

void ledLatency (int f){ // для задержки отображения пика

    if(g<f && f<=12){
      g=f;
      onLedOne(g-1);
    }else if(h<100 && g>0){
       onLedOne(g-1);
       h++;
      }else if(g>0){
       g--;
       onLedOne(g-1);
       h=0;
      }else{
       h=0;
    }
}

void ledon (int a, int b, int c, int d){ //зажигает определённый светодиод
  pinMode(a, OUTPUT);
  digitalWrite(a, HIGH);   
  pinMode(b, INPUT);
  pinMode(c, INPUT);
  pinMode(d, OUTPUT);
  digitalWrite(d, LOW);
  delayMicroseconds(1);
 
  for(int i=0; i<5; i++)//очищаем входы
  pinMode(i, INPUT);
}

void onLedOne (int i){ //зажигает только один выбранный светодиод

    int a = numLed[i][0];
    int b = numLed[i][1];
    int c = numLed[i][2];
    int d = numLed[i][3];
    ledon (a, b, c, d);
}

void onLed (int f){  //исходя из полученного уровня зажигает свотодиоды 

  for (int j=0; j<f; j++)
    onLedOne(j);
  ledLatency(f);
}

void loop() {
  
 int val = 0;
 for(int i=0; i<20; i++)
   val = val+analogRead(3);
   if(val<20 && val>0)
     val = 20;
   if(val<40 && val>20)
     val =40;
   if(val<80 && val>40)
     val = 340;
   val = val/20;
   
  //onLed (map(val, 0, 1023, 0, 12));
  //delayMicroseconds(1); 
     
  if(val==0){
    
    if(k>3000){
      onLedOne(11);
      for(int i=0; i<1000; i++){
        pinMode(3, OUTPUT);
      digitalWrite(3, HIGH);
      //delayMicroseconds(1);
      digitalWrite(3, LOW);
      }
      delayMicroseconds(300);
    }
    k++;
    
    for (int i=0; i<=4; i++)
      pinMode (i, INPUT);
      
    ledLatency(0);
    delayMicroseconds(10);
    
  }else if( val<2){
    onLed (map(val, 0, 1, 0, 1));
    k=0;

  }else if(val<70){
    onLed (map(val, 2, 69, 2, 6));
    k=0;

  }else if(val<141){
    onLed (map(val, 70, 140, 6, 9));
    k=0;

  }else if(val<191){
    onLed (map(val, 141, 190, 9, 10));
    k=0;
    
    }else if(val<251){
    onLed (map(val, 191, 250, 10, 12));

  }else{
    for (int i=0; i<=11; i++){
      onLedOne(11-i);
      g=12;
    delay(1);
    
     if(k>100){
      for(int i=0; i<100; i++){
        pinMode(3, OUTPUT);
      digitalWrite(3, HIGH);
      //delayMicroseconds(1);
      digitalWrite(3, LOW);
      }
    }
  }
    k++;
  }
  
}

http://hlt.media.mit.edu/?p=1229

Вот видео то что получилось: http://www.youtube.com/watch?v=qj3i9LEJvYg

Светодиоды подключал по такой схеме:

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

А если использовать семисегментник типо такого: 

Такой метод ведь подойдёт для него правда? Только подозреваю нужны резисторы будут.

maksim
Offline
Зарегистрирован: 12.02.2012

HWman пишет:

 

Такой метод ведь подойдёт для него правда?

Если под "методом" вы подразумеваете динамическую индикацию, то этот дисплей будет работать только именно таким "методом".

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

...таким методом подключения семисегментника к Arduino, для экономии ног :)

xplp
Offline
Зарегистрирован: 21.12.2012

Судя по колическтву ног на этом сигментном индикаторе, там и так уже разведено примерно как у меня на картинке, только больше ног используется, например если задействовать 4 ноги то можно задействовать 12 светодиодов, 5 ног 20 светодиодов, 6 - 30, 7 - 42, 8 - 56, 9 - 72, 10 -90, 11 - 110, 12 - 132, 13- 156... и т.д. (=  

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Угу... я уже это понял :)

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Жаль на ATtiny13 невлезает :( 1 932 байт

 

maksim
Offline
Зарегистрирован: 12.02.2012

Если оптимизировать код и отказаться от дуино-функций, то скорее всего влезет.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Воспользовался Вашим примером в моей теме "Размер скетча в двоичном коде: 882 байт (из 1 024 байт максимум)" Вроде так должно работать





















const int numLed[12][4] = {
          {0,1,2,4}, //1
          {0,1,4,2}, //2
          {0,2,4,1}, //3
          {1,0,2,4}, //4
          {1,0,4,2}, //5
          {1,2,4,0}, //6
          {2,1,0,4}, //7
          {2,0,4,1}, //8
          {2,4,1,0}, //9
          {4,0,1,2}, //10
          {4,0,2,1}, //11
          {4,2,1,0}, //12
}; 

int g = 11;
int h = 0;
int k = 0;
 
void setup() {                
  
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, INPUT);
  pinMode(4, OUTPUT);
  
}

void ledLatency (int f){ // для задержки отображения пика

    if(g<f && f<=12){
      g=f;
      onLedOne(g-1);
    }else if(h<100 && g>0){
       onLedOne(g-1);
       h++;
      }else if(g>0){
       g--;
       onLedOne(g-1);
       h=0;
      }else{
       h=0;
    }
}

void ledon (int a, int b, int c, int d){ //зажигает определённый светодиод
  pinMode(a, OUTPUT);
  digitalWrite(a, HIGH);   
  pinMode(b, INPUT);
  pinMode(c, INPUT);
  pinMode(d, OUTPUT);
  digitalWrite(d, LOW);
  delayMicroseconds(1);
 
  for(int i=0; i<5; i++)//очищаем входы
  pinMode(i, INPUT);
}

void onLedOne (int i){ //зажигает только один выбранный светодиод

    int a = numLed[i][0];
    int b = numLed[i][1];
    int c = numLed[i][2];
    int d = numLed[i][3];
    ledon (a, b, c, d);
}

void onLed (int f){  //исходя из полученного уровня зажигает свотодиоды 

  for (int j=0; j<f; j++)
    onLedOne(j);
  ledLatency(f);
}

void loop() {
  
 int val = 0;
 for(int i=0; i<20; i++)
   val = val+ADC_READ();
   if(val<20 && val>0)
     val = 20;
   if(val<40 && val>20)
     val =40;
   if(val<80 && val>40)
     val = 340;
   val = val/20;
   
  //onLed (map(val, 0, 1023, 0, 12));
  //delayMicroseconds(1); 
     
  if(val==0){
    
    if(k>3000){
      onLedOne(11);
      for(int i=0; i<1000; i++){
        pinMode(3, OUTPUT);
      digitalWrite(3, HIGH);
      //delayMicroseconds(1);
      digitalWrite(3, LOW);
      }
      delayMicroseconds(300);
    }
    k++;
    
    for (int i=0; i<=4; i++)
      pinMode (i, INPUT);
      
    ledLatency(0);
    delayMicroseconds(10);
    
  }else if( val<2){
    onLed (map(val, 0, 1, 0, 1));
    k=0;

  }else if(val<70){
    onLed (map(val, 2, 69, 2, 6));
    k=0;

  }else if(val<141){
    onLed (map(val, 70, 140, 6, 9));
    k=0;

  }else if(val<191){
    onLed (map(val, 141, 190, 9, 10));
    k=0;
    
    }else if(val<251){
    onLed (map(val, 191, 250, 10, 12));

  }else{
    for (int i=0; i<=11; i++){
      onLedOne(11-i);
      g=12;
    delayMicroseconds(1);
    
     if(k>100){
      for(int i=0; i<100; i++){
        pinMode(3, OUTPUT);
      digitalWrite(3, HIGH);
      //delayMicroseconds(1);
      digitalWrite(3, LOW);
      }
    }
  }
    k++;
  }
  
}
int ADC_READ() // запустим АЦП или что?
	{
	  ADMUX = 3; // ADC pin
	  ADCSRA |= 1<<ADEN;
	  ADCSRA |= 1<<ADSC;
	  while(!(ADCSRA & (1<<ADIF)));
	  ADCSRA |= 1<<ADIF; 
	  byte low  = ADCL;
	  byte high = ADCH;
	  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
}

После прочтения маленькой статейки я решил пойти дальше, тоесть укоротил до 716 байт:

















#include <avr/io.h>
const int numLed[12][4] = {
          {0,1,2,4}, //1
          {0,1,4,2}, //2
          {0,2,4,1}, //3
          {1,0,2,4}, //4
          {1,0,4,2}, //5
          {1,2,4,0}, //6
          {2,1,0,4}, //7
          {2,0,4,1}, //8
          {2,4,1,0}, //9
          {4,0,1,2}, //10
          {4,0,2,1}, //11
          {4,2,1,0}, //12
}; 

int g = 11;
int h = 0;
int k = 0;
 
void setup() {                
  DDRB = 0b10111;
  //DDRB |= (1<<0); 
  //DDRB |= (1<<1);
  //DDRB |= (1<<2);
  //DDRB |= (0<<3);
  //DDRB |= (1<<4);
  
}

void ledLatency (int f){ // для задержки отображения пика

    if(g<f && f<=12){
      g=f;
      onLedOne(g-1);
    }else if(h<100 && g>0){
       onLedOne(g-1);
       h++;
      }else if(g>0){
       g--;
       onLedOne(g-1);
       h=0;
      }else{
       h=0;
    }
}

void ledon (int a, int b, int c, int d){ //зажигает определённый светодиод
  DDRB |= (1<<a);
  PORTB |= (1<<a);   
  DDRB |= (0<<b);
  DDRB |= (0<<c);
  DDRB |= (1<<d);
  PORTB &= ~(1<<d);
  delayMicroseconds(1);
 
  for(int i=0; i<5; i++)//очищаем входы
  DDRB |= (0<<i);
}

void onLedOne (int i){ //зажигает только один выбранный светодиод

    int a = numLed[i][0];
    int b = numLed[i][1];
    int c = numLed[i][2];
    int d = numLed[i][3];
    ledon (a, b, c, d);
}

void onLed (int f){  //исходя из полученного уровня зажигает свотодиоды 

  for (int j=0; j<f; j++)
    onLedOne(j);
  ledLatency(f);
}

void loop() {
  
 int val = 0;
 for(int i=0; i<20; i++)
   val = val+ADC_READ();
   if(val<20 && val>0)
     val = 20;
   if(val<40 && val>20)
     val =40;
   if(val<80 && val>40)
     val = 340;
   val = val/20;
   
  //onLed (map(val, 0, 1023, 0, 12));
  //delayMicroseconds(1); 
     
  if(val==0){
    
    if(k>3000){
      onLedOne(11);
      for(int i=0; i<1000; i++){
        DDRB |= (1<<3);
      PORTB |= (1<<3);
      //delayMicroseconds(1);
      PORTB &= ~(1<<3);
      }
      delayMicroseconds(300);
    }
    k++;
    
    for (int i=0; i<=4; i++)
      DDRB |= (0<<i);
      
    ledLatency(0);
    delayMicroseconds(10);
    
  }else if( val<2){
    onLed (map(val, 0, 1, 0, 1));
    k=0;

  }else if(val<70){
    onLed (map(val, 2, 69, 2, 6));
    k=0;

  }else if(val<141){
    onLed (map(val, 70, 140, 6, 9));
    k=0;

  }else if(val<191){
    onLed (map(val, 141, 190, 9, 10));
    k=0;
    
    }else if(val<251){
    onLed (map(val, 191, 250, 10, 12));

  }else{
    for (int i=0; i<=11; i++){
      onLedOne(11-i);
      g=12;
    delayMicroseconds(1);
    
     if(k>100){
      for(int i=0; i<100; i++){
        DDRB |= (1<<3);
      PORTB |= (1<<3);
      //delayMicroseconds(1);
      PORTB &= ~(1<<3);
      }
    }
  }
    k++;
  }
  
}
int ADC_READ() // запустим АЦП или что?
	{
	  ADMUX = 3; // ADC pin
	  ADCSRA |= 1<<ADEN;
	  ADCSRA |= 1<<ADSC;
	  while(!(ADCSRA & (1<<ADIF)));
	  ADCSRA |= 1<<ADIF; 
	  byte low  = ADCL;
	  byte high = ADCH;
	  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
}	  

Компилируется без проблем оба, но работоспособность второго не гарантирую.

Завтра в протэусе смоделирую и проверю

 

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Работает первый вариант:

 Второй только D6, D9, D12 завсечивает и всё...

Внимание на количество предупреждений :)

 

maksim
Offline
Зарегистрирован: 12.02.2012

Не заработает, хотябы потому что вы потеряли в функции int ADC_READ() последнюю строку и функция у вас ничего не возвращает

   ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
   return (high << 8) | low;
}

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

 

Размер скетча в двоичном коде: 1 742 байт (из 1 024 байт максимум)

:(

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Пробовал отсекать куски кода и смотрел что жрёт больше памяти, и когда дошёл до map-ов(от строки 114) тогда уже перевал...

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Методом научного... ну поняли, получилось вот такое:



const unsigned int numLed[12][4] = {
          {0,1,2,4}, //1
          {0,1,4,2}, //2
          {0,2,4,1}, //3
          {1,0,2,4}, //4
          {1,0,4,2}, //5
          {1,2,4,0}, //6
          {2,1,0,4}, //7
          {2,0,4,1}, //8
          {2,4,1,0}, //9
          {4,0,1,2}, //10
          {4,0,2,1}, //11
          {4,2,1,0}, //12
}; 

unsigned char g = 11;
unsigned char h = 0;
unsigned char k = 0;
 
void setup() {  
  
DDRB = 0b10111;
  
}

void ledLatency (unsigned char f){ // для задержки отображения пика

    if(g<f && f<=12){
      g=f;
      onLedOne(g-1);
    }else if(h<100 && g>0){
       onLedOne(g-1);
       h++;
      }else if(g>0){
       g--;
       onLedOne(g-1);
       h=0;
      }else{
       h=0;
    }
}

void ledon (unsigned char a,unsigned char b,unsigned char c,unsigned char d){ //зажигает определённый светодиод
  DDRB |= (1<<a);
  PORTB |= (1<<a);   
  DDRB |= (0<<b);
  DDRB |= (0<<c);
  DDRB |= (1<<d);
  PORTB &= ~(1<<d);
  delayMicroseconds(1);
 
  for(unsigned char i=0; i<5; i++)//очищаем входы
  DDRB |= (0<<i);
}

void onLedOne (unsigned char i){ //зажигает только один выбранный светодиод

   unsigned char a = numLed[i][0];
   unsigned char b = numLed[i][1];
   unsigned char c = numLed[i][2];
   unsigned char d = numLed[i][3];
    ledon (a, b, c, d);
}

void onLed (unsigned char f){  //исходя из полученного уровня зажигает свотодиоды 

  for (unsigned char j=0; j<f; j++)
    onLedOne(j);
  ledLatency(f);
}

void loop() {
  
unsigned int val = 0;
 for(unsigned char i=0; i<20; i++)
   val = val + ADC_READ();
   if(val<20 && val>0)
     val = 20;
   if(val<40 && val>20)
     val =40;
   if(val<80 && val>40)
     val = 340;
   val = val/20;
   
  //onLed (map(val, 0, 1023, 0, 12));
  //delayMicroseconds(1); 
     
  if(val==0){
    
    if(k>3000){
      onLedOne(11);
      for(unsigned int i=0; i<1000; i++){
        DDRB |= (1<<3);
      PORTB |= (1<<3);
      //delayMicroseconds(1);
      PORTB &= ~(1<<3);
      }
      delayMicroseconds(300);
    }
    k++;
    
    for (unsigned char i=0; i<=4; i++)
      DDRB |= (0<<i);
      
    ledLatency(0);
    delayMicroseconds(10);
    //
    }else if( val<2){
   onLed (val/20);
    k=0;
    //
  }else if(val<70){
    onLed ((val/13) + 1);
    k=0;

  }else if(val<141){
    onLed ((val/28) + 5);
    k=0;

  }else if(val<191){
    onLed ((val/95) + 8);
    k=0;
    
    }else if(val<251){
    onLed ((val/83) + 9);
    k=0;
  }else{
    for (unsigned char i=0; i<=11; i++){
      onLedOne(11-i);
      g=12;
    delay(1);
    
     if(k>100){
      for(unsigned char i=0; i<100; i++){
       DDRB |= (1<<3);
      PORTB |= (1<<3);
      //delayMicroseconds(1);
      PORTB &= ~(1<<3);
      }
    }
  }
    k++;
  } 
}
unsigned int ADC_READ() // запустим АЦП или что?
	{
	  ADMUX = 3; // ADC pin
	  ADCSRA |= 1<<ADEN;
	  ADCSRA |= 1<<ADSC;
	  while(!(ADCSRA & (1<<ADIF)));
	  ADCSRA |= 1<<ADIF; 
	  byte low  = ADCL;
	  byte high = ADCH;
	  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
        return (high << 8) | low;
}

Вроде что-то светится но протэус выдаёт много ошибок...

http://www.youtube.com/watch?v=dRhFk66AbSs&feature=youtu.be

upd изменил тип даних

xplp
Offline
Зарегистрирован: 21.12.2012

Можно так зарезать код, будет без красивостей излишних(void ledLatency), но зато меньше весить, 1 240 байт. Также убрано всё что касается переменной k, оно без надобности. Эта переменная нужна для того чтоб при пропадании звука подавать сигналы, на вход повесить пищалку и она будет пищать. В общем как то так:





const unsigned int numLed[12][4] = {
          {0,1,2,4}, //1
          {0,1,4,2}, //2
          {0,2,4,1}, //3
          {1,0,2,4}, //4
          {1,0,4,2}, //5
          {1,2,4,0}, //6
          {2,1,0,4}, //7
          {2,0,4,1}, //8
          {2,4,1,0}, //9
          {4,0,1,2}, //10
          {4,0,2,1}, //11
          {4,2,1,0}, //12
}; 

//unsigned char g = 11;
//unsigned char h = 0;
unsigned int val = 0;
//unsigned char k = 0;
 
void setup() {  
  
DDRB = 0b10111;
  
}

/*void ledLatency (unsigned char f){ // для задержки отображения пика

    if(g<f && f<=12){
      g=f;
      onLedOne(g-1);
    }else if(h<100 && g>0){
       onLedOne(g-1);
       h++;
      }else if(g>0){
       g--;
       onLedOne(g-1);
       h=0;
      }else{
       h=0;
    }
}*/

void ledon (unsigned char a,unsigned char b,unsigned char c,unsigned char d){ //зажигает определённый светодиод
  DDRB |= (1<<a);
  PORTB |= (1<<a);   
  DDRB |= (0<<b);
  DDRB |= (0<<c);
  DDRB |= (1<<d);
  PORTB &= ~(1<<d);
  delayMicroseconds(1);
 
  for(unsigned char i=0; i<5; i++)//очищаем входы
  DDRB |= (0<<i);
}

void onLedOne (unsigned char i){ //зажигает только один выбранный светодиод

   unsigned char a = numLed[i][0];
   unsigned char b = numLed[i][1];
   unsigned char c = numLed[i][2];
   unsigned char d = numLed[i][3];
    ledon (a, b, c, d);
}

void onLed (unsigned char f){  //исходя из полученного уровня зажигает свотодиоды 

  for (unsigned char j=0; j<f; j++)
    onLedOne(j);
  //ledLatency(f);
}

void loop() {
  

 for(unsigned char i=0; i<20; i++)
   val = val + ADC_READ();
   /*if(val<20 && val>0)
     val = 20;
   if(val<40 && val>20)
     val =40;
   if(val<80 && val>40)
     val = 340;
   val = val/20;
   */
  //onLed (map(val, 0, 700, 0, 12));
  //delayMicroseconds(1); 
     
  if(val==0){
   
     
    //ledLatency(0);
    delayMicroseconds(10);
    //
    }else if( val<2){
   onLed (val/20);
  
    //
  }else if(val<70){
    onLed ((val/13) + 1);
   

  }else if(val<141){
    onLed ((val/28) + 5);
   

  }else if(val<191){
    onLed ((val/95) + 8);
   
    
    }else if(val<251){
    onLed ((val/83) + 9);
  
  }else{
    //for (unsigned char i=0; i<=11; i++){
     // onLedOne(11-i);
     // g=12;
    delay(1);

  //}
   
  } 
}
unsigned int ADC_READ() // запустим АЦП или что?
	{
	  ADMUX = 3; // ADC pin
	  ADCSRA |= 1<<ADEN;
	  ADCSRA |= 1<<ADSC;
	  while(!(ADCSRA & (1<<ADIF)));
	  ADCSRA |= 1<<ADIF; 
	  byte low  = ADCL;
	  byte high = ADCH;
	  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
        return (high << 8) | low;
}

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Спасибо, но не светятся вообще, что то я напартачил...

Вот бы не эти map-ы было бы всё прекрасно, много памяти они занимают, а то как я реализовал скорей всего неправильно...

Да и char и unsigned int брать как тип данных не было ошибкой?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Вот набросал:

const int numLed[12][4] = {
          {0,1,2,4}, //1
          {0,1,4,2}, //2
          {0,2,4,1}, //3
          {1,0,2,4}, //4
          {1,0,4,2}, //5
          {1,2,4,0}, //6
          {2,1,0,4}, //7
          {2,0,4,1}, //8
          {2,4,1,0}, //9
          {4,0,1,2}, //10
          {4,0,2,1}, //11
          {4,2,1,0}, //12
}; 

int g = 11;
int h = 0;
//unsigned int val = 0; 
 
void setup() {                
DDRB = 0b10111;
  
}

void ledLatency (int f){ // для задержки отображения пика

    if(g<f && f<=12){
      g=f;
      onLedOne(g-1);
    }else if(h<100 && g>0){
       onLedOne(g-1);
       h++;
      }else if(g>0){
       g--;
       onLedOne(g-1);
       h=0;
      }else{
       h=0;
    }
}

void ledon (int a, int b, int c, int d){ //зажигает определённый светодиод
   DDRB |= (1<<a);
  PORTB |= (1<<a);   
  DDRB |= (0<<b);
  DDRB |= (0<<c);
  DDRB |= (1<<d);
  PORTB &= ~(1<<d);
  //delayMicroseconds(1);
 
  for(int i=0; i<5; i++) //очищаем входы
  DDRB &= ~(1<<i); 
}

void onLedOne (int i){ //зажигает только один выбранный светодиод

    int a = numLed[i][0];
    int b = numLed[i][1];
    int c = numLed[i][2];
    int d = numLed[i][3];
    ledon (a, b, c, d);
}

void onLed (int f){  //исходя из полученного уровня зажигает свотодиоды 

  for (int j=0; j<f; j++)
    onLedOne(j);
  ledLatency(f);
}

void loop() {
  //val = analogRead(3); 
  onLed ((analogRead(3) / 85));
  //delayMicroseconds(1); 
  
}

В протэусе и с 85 тинькой всё работает, а с 13-й нет, тупо ничего не происходит.

ЗЫ если pinMode(i, INPUT);  сменить на DDRB |= (0<<i); то при низком уровне вместо того чтобы светился 1 диод светятся все три(6,9,12)

 

maksim
Offline
Зарегистрирован: 12.02.2012

pinMode(i, INPUT);  нельзя заменить на DDRB |= (0<<i);
"После прочтения маленькой статейки..."   DDRB &= ~(1<<i);

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Итак, пробовал зашивать в ATtiny13 код из первого сообщения, но немного урезан:





#define F_CPU 9600000UL  // 9.6 MHz
const int numLed[12][4] = {
          {0,1,2,4}, //1
          {0,1,4,2}, //2
          {0,2,4,1}, //3
          {1,0,2,4}, //4
          {1,0,4,2}, //5
          {1,2,4,0}, //6
          {2,1,0,4}, //7
          {2,0,4,1}, //8
          {2,4,1,0}, //9
          {4,0,1,2}, //10
          {4,0,2,1}, //11
          {4,2,1,0}, //12
}; 

int g = 11;
int h = 0;
int k = 0;
 
void setup() {                
  
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, INPUT);
  pinMode(4, OUTPUT);
  
}

void ledLatency (int f){ // для задержки отображения пика

    if(g<f && f<=12){
      g=f;
      onLedOne(g-1);
    }else if(h<100 && g>0){
       onLedOne(g-1);
       h++;
      }else if(g>0){
       g--;
       onLedOne(g-1);
       h=0;
      }else{
       h=0;
    }
}

void ledon (int a, int b, int c, int d){ //зажигает определённый светодиод
  pinMode(a, OUTPUT);
  digitalWrite(a, HIGH);   
  pinMode(b, INPUT);
  pinMode(c, INPUT);
  pinMode(d, OUTPUT);
  digitalWrite(d, LOW);
  delayMicroseconds(1);
 
  for(int i=0; i<5; i++)//очищаем входы
  pinMode(i, INPUT);
}

void onLedOne (int i){ //зажигает только один выбранный светодиод

    int a = numLed[i][0];
    int b = numLed[i][1];
    int c = numLed[i][2];
    int d = numLed[i][3];
    ledon (a, b, c, d);
}

void onLed (int f){  //исходя из полученного уровня зажигает свотодиоды 

  for (int j=0; j<f; j++)
    onLedOne(j);
  ledLatency(f);
}

void loop() {

onLed ((analogRead(3) / 85));

}

 

На arduino всё работает, без проблем, но на ATtiny13 точно такой же код напрочь не хочет работать:

http://www.youtube.com/watch?v=Uw00Od_fTvk

Что же может быть не так? Может чего-то не хватает?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

...может какого-то кеша или ещё чего-то...

Клапауций
Offline
Зарегистрирован: 10.02.2013

HWman пишет:

...может какого-то кеша или ещё чего-то...

попробуй #define F_CPU 8000000UL  // 8 MHz

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

пробовал, и пробовал стереть даже эту строчку - нифига

Клапауций
Offline
Зарегистрирован: 10.02.2013

HWman пишет:

пробовал, и пробовал стереть даже эту строчку - нифига

тогда не знаю

странно оно, компилится но неправильно работает.

maksim
Offline
Зарегистрирован: 12.02.2012

Да ничего строанного. 

HWman, вы же уже вроде освоили работу с регистрами, так зачем пользуете дуинофункции?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Перепробовал всё что в этой теме есть, ничего не пашет, может мощи не хватает тиньке?

Что есть у 85-й чего нет у 13-?

На UNO всё работало нормально, залил код на тини13 и...  видео выше выкладывал...

Могу кинуть сюда файлы протеуса и посмотрете.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Думаю вся проблема в digitalWrite().

Вот digitalWrite() для тини х5 как выглядит:





void digitalWrite(uint8_t pin, uint8_t val)
{
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	volatile uint8_t *out;

	if (port == NOT_A_PIN) return;

	// If the pin that support PWM output, we need to turn it off
	// before doing a digital write.
  turnOffPWM( pin );

	out = portOutputRegister(port);

	if (val == LOW) {
		uint8_t oldSREG = SREG;
    cli();
		*out &= ~bit;
		SREG = oldSREG;
	} else {
		uint8_t oldSREG = SREG;
    cli();
		*out |= bit;
		SREG = oldSREG;
	}
}

А вот так для тини 13:





void digitalWrite(uint8_t pin, uint8_t val){
	if(pin > 5 || pin < 0){return;}
	if(pin<2){turnOffPWM(pin);} //If its a PWM pin, make sure the PWM is off
	if(!val){
		PORTB &= ~_BV(pin);
	} else {
		PORTB |= _BV(pin);
	}
}

Если эту функцию поправить должным  образом то думаю данный код и на тини 13 заработает если кое что урезать.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

ТС, а на какой частоте работала тинька? 9.6?

xplp
Offline
Зарегистрирован: 21.12.2012

Код который влезает в Attiny13:

const byte numLed[12][2] = {
          {0,4}, //1
          {0,2}, //2
          {0,1}, //3
          {1,4}, //4
          {1,2}, //5
          {1,0}, //6
          {2,4}, //7
          {2,1}, //8
          {2,0}, //9
          {4,2}, //10
          {4,1}, //11
          {4,0}, //12
}; 

 
void setup() {                
  
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, INPUT);
  pinMode(4, OUTPUT);
  
}
void clearIn(){
  for(byte i=0; i<5; i++)//очищаем входы
  pinMode(i, INPUT);
}


void ledon (byte a, byte d){ //зажигает определённый светодиод
  clearIn();
  
  pinMode(a, OUTPUT);
  pinMode(d, OUTPUT);
  
  digitalWrite(a, HIGH);   
  digitalWrite(d, LOW);
  
  delayMicroseconds(1);
 
  clearIn();
}

void onLedOne (byte i){ //зажигает только один выбранный светодиод
//if(i<=12 && i>=0){
    //i--;
    byte a = numLed[i][0];
    byte d = numLed[i][1];
    ledon (a, d);
  //}
}
void onLed (byte f){  //исходя из полученного уровня зажигает светодиоды 

  for (byte j=0; j<=f; j++)
    onLedOne(j);
}

void loop() {
  
  onLed(analogRead(3)/83);

}

 

vovka1021
Offline
Зарегистрирован: 02.02.2016

схему подключения можно увидеть?

xplp
Offline
Зарегистрирован: 21.12.2012

vovka1021 пишет:

схему подключения можно увидеть?

Схема в #9 комментарии. Диоды к 0,1,2,4 выходам, потенциометр или выход звука от какого нибудь источника, к 3му аналоговому входу.

vovka1021
Offline
Зарегистрирован: 02.02.2016

код для Attiny13 какой рабочий? в #27 коментарии будет работать?

xplp
Offline
Зарегистрирован: 21.12.2012

да, этот код я проверял на железке, всё работало от потенциометра, от аудио выхода не проверял.