пятница, 21 июня 2013 г.

Пример использования платы BlockProto2 - термометр из LM35 и светодиодного дисплея GNQ-5641


Отпишусь, как можно из платы BlockProto2 сделать небольшую BreadBoard, т.е. беспаечную макетную плату, ну и как на ее базе сконструировать на коленке термометр.
Итак, во-первых, нужно в плату BlockProto2 впаять цанговые однорядные панельки.
Я купил 6 штук по 40 пинов и разломал их на 9 штук по 20 пинов (8 штук в протоплощадки и одну на цифровую линию шины BlockDuino), две по 8 пинов (на площадки +5V и GND) и две по 9 пинов (на оставшуюся линию шины BlockDuino). Примерно вот так:
Теперь плата готова к использованию. Тут главное не запутаться, где какой пин. В общем, надо поглядывать на схему расположения площадок:

А дальше все просто, берем светодиодный индикатор GNQ-5641, датчик температуры LM35 и 7 проводов. Заметьте, всего семь!!! проводков, несмотря на то, что нам нужно подключить 12 ножек индикатора и 3 ножки датчика!
BlockProto - термометр из LM35 и светодиодного дисплея GNQ-5641
 Как так? А все просто, мы нижние 6 ножек индикатора поместим сразу на разъем цифровых портов D8-D13.
Дальше вставляем индикатор в нужное место, нужное - это значит что нижний ряд ножек, числом в шесть штук должен встать в линейку цифровых портов D8÷D13, а верхние при этом втыкаются в разъемы в позицию P6, Q6, R6, S6, T6, U6.
Затем берется 6 проводов и верхние свободные ножки подключаются к свободным портам. Так как корпус индикатора перекрывает доступ к портам D4÷D7, то подключаем к портам D1, D2, A2, A3, A4, A5.
Порядок подключения не принципиален, я подключал так:
A2
D1
D2
A5(D19)
A4(D18)
A3(D17)
DIG1
A
F
DIG2
DIG3
B







E
D
Dp
C
G
DIG4
D8
D9
D10
D11
D12
D13
Т.е. провода соединяли: U8-MA3, T8-MA4, S8-MA5, R8-MD2, Q8-MD1, P8-MA2
Примечание: зеленым цветом обозначены ножки светодиодного индикатора; Буква М перед адресом обозначает что пин находится на площадке шины BlockDuino, т.е. MD8 - цифровой порт D8, MA3 - аналоговый порт A3; в отличие от позиции D3 - третья площадка в ряду D на протоплощадке!!! 
Для проверки правильности подключения и работоспособности загружаем проверочный код:
Код под спойлером:

int DigPins[] = { A2, A5 ,A4, 13 };
int SegPins[] = { A1,A3,11,9,8,3,12,10 };

void setup() {
  for (byte digit=0;digit<4;digit++) {
    pinMode(DigPins[digit], OUTPUT);
    digitalWrite(DigPins[digit], LOW);
  }
  for (byte seg=0;seg<8;seg++) {
    pinMode(SegPins[seg], OUTPUT);
    digitalWrite(SegPins[seg], HIGH);
  }
}

void loop() {
  for (byte digit=0;digit<4;digit++) {
    digitalWrite(DigPins[digit], HIGH);
      for (byte seg=0;seg<8;seg++) {
        digitalWrite(SegPins[seg], LOW);
//        delay(250);
      }
    digitalWrite(DigPins[digit], LOW);  
    for (byte seg=0;seg<8;seg++) {
      digitalWrite(SegPins[seg], HIGH);
    }
  } 
}


При работе кода на индикаторе последовательно (A, B, C,..,G, Dp) зажигаются светодиоды по очереди на каждой цифре.

Если же мы видим нормально зажигающиеся последовательно восьмерки, то пора подключить и датчик температуры LM35. Так как выводы у него расположены в последовательности +5V_Signal_Gnd, а мне удобнее Gnd_+5V_Sig, то нужно слегка подогнуть выводы, чтобы +5V и Sig поменялись местами. И затем этот девайс втыкаем в разъем, так чтоб выводы питания вошли в два крайних слева ряда, а вывод сигнала в позицию A7.


Соответственно подключаем вывод датчика проводом к свободному аналоговому порту, например A0, т.е. из позиции A5 в позицию MA0.
Теперь имеем примерно такую картину:
Теперь осталось дело за малым - оживить и добиться результата. Велосипед изобретать не хотелось, поэтому слегка копнув просторы интернета и опробировав разные варианты, остановился на коде выковыряном из форума сайта roboforum.ru, тот рабочий код, который в самом конце ветки размещен. Выбрал его, потому как только он использует прерывания для отображения символов на дисплее, ихмо, только так и нужно.
Слегка допилив получил вот такой код:

Код под спойлером:

#include <avr/interrupt.h>

//Снять комментарий для индикаторов с общим катодом
//#define OKAT 

bool LLOW = LOW;
bool HHIGH = HIGH;
int pin = 0; // analog pin
float tempc = 0; // temperature variables

int rdigs[] = {13, A4 ,A5, A2};
//              A  B  C  D  E  F  G  H
//int rsegs[] = { 1, 2, 3, 4, 5, 6, 7, 8}; 
int rsegs[] = { A1,A3,11,9,8,3,12,10}; 
bool digits[15][8] = {
  {1, 1, 1, 1, 1, 1, 0, 0},  //0
  {0, 1, 1, 0, 0, 0, 0, 0},  //1
  {1, 1, 0, 1, 1, 0, 1, 0},  //2
  {1, 1, 1, 1, 0, 0, 1, 0},  //3
  {0, 1, 1, 0, 0, 1, 1, 0},  //4
  {1, 0, 1, 1, 0, 1, 1, 0},  //5
  {1, 0, 1, 1, 1, 1, 1, 0},  //6
  {1, 1, 1, 0, 0, 0, 0, 0},  //7
  {1, 1, 1, 1, 1, 1, 1, 0},  //8
  {1, 1, 1, 1, 0, 1, 1, 0},  //9
  {0, 0, 0, 0, 0, 0, 0, 0},  //none
  {0, 0, 0, 0, 0, 0, 1, 0},  //-
  {1, 0, 0, 1, 1, 1, 1, 1},  //E.
  {0, 0, 0, 0, 1, 0, 1, 1},  //r.
  {1, 1, 1, 1, 1, 1, 0, 1}   //0.
}; 
int cdigit = 0;
int odigit = 0;
int displ[] = {0, 8, 4, 9};

void cleardisplay();
void displayErr(int err);


// Подпрограмма прерывания
ISR(TIMER2_OVF_vect) {
//  return;
  int dig;
  if(cdigit < 0 || cdigit > 3) cdigit = 0;
  digitalWrite(rdigs[odigit], LLOW);
  dig = abs(displ[cdigit]);
#ifdef OKAT
  if(displ[cdigit] < 0) digits[dig][7] = 0; //Проверяется рисовать ли точку cdigit - позиция точки
  else digits[dig][7] = 1;
#else  
  if(displ[cdigit] < 0) digits[dig][7] = 1; //Проверяется рисовать ли точку cdigit - позиция точки
  else digits[dig][7] = 0;
#endif
  for(int i = 0; i < 8; i++) digitalWrite(rsegs[i], !(digits[dig][i]));
  digitalWrite(rdigs[cdigit], HHIGH);
  odigit = cdigit;
  cdigit++;
  TCNT2 = 0;
}

void setup() {
  int i;
#ifdef OKAT
  int j;
  LLOW = HIGH;
  HHIGH = LOW;
  for(i=0; i<15; i++) {
   for(j=0; j<8; j++) {
     if(digits[i][j]==0) digits[i][j]=1;
     else digits[i][j]=0;
   }
  }
#endif
  for(i=0; i<4; i++) {
    pinMode(rdigs[i], OUTPUT);
    digitalWrite(rdigs[i], LLOW);
  }
  for(i=0; i<8; i++) {
    pinMode(rsegs[i], OUTPUT);
    digitalWrite(rsegs[i], LLOW);
  }
  //Установка делителей таймера
  TCCR2A = 0;
  TCCR2B |= 1<<CS22;
  TCCR2B &= ~((1<<CS21) | (0<<CS20));
  TCCR2B &= ~((1<<WGM21) | (1<<WGM20));
  TIMSK2 |= 1<<TOIE2; 
  //reset timer
  TCNT2 = 0;
  cleardisplay();
}

void loop() {
  tempc = ( 5.0 * analogRead(pin) * 100.0) / 1024.0;
  
  displayTemperature(tempc);
  delay(1500);
}

void displayTemperature(float term) {
  int bdis[4] = {10, 10, 10, 10};
  int cycle;
  int temp = 100*abs(term);

  cycle = 2;
  while(temp > 0) {
    for(int i=0; i<3; i++) bdis[i] = bdis[i+1];
    bdis[3] = temp % 10;
    if(cycle==0) {
      if(bdis[3]==0) bdis[3] = -14;
      else bdis[3] *= -1;
    }
    temp /= 10;
    cycle--;
  }
  if(term<0) {
    for(int i=0; i<3; i++) bdis[i] = bdis[i+1];
    bdis[3] = 11;
    if(cycle==0) bdis[3] *= -1;
  }
  for(int i=0; i<4; i++) displ[i] = bdis[i];
}

void cleardisplay() {
  for(int i=0; i<4; i++) displ[i] = 10;
}

void displayErr(int err) {
  displ[0] = err;
  displ[1] = -13;
  displ[2] = -13;
  displ[3] = -12;
}



В итоге мы потратив немного времени и мыслительных усилий создали вполне работающее устройство даже без использования паяльника (при условии готовой платы BlockProto2_BreadBoard).