Самая экономичная LED -индикация, проблема с "двоеточием".

None
Offline
Зарегистрирован: 15.01.2016

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

Почему-то не происходит инвертирование переменной S, отвечающей за мигание "двоеточия" (65,66 строка кода) (76 строка отвечает за отображение "двоеточия").

PS: Часы-минуты и, возможно, дата будет браться из DS3132, когда он приедет.

Вот код для индикатора с общим катодом:

byte A=2;   //Символ A, сверху
byte B=3;   //Символ B, сверху справо
byte C=4;   //Символ C, снизу справо
byte D=5;   //Символ D, нижний
byte E=6;   //Символ E, снизу слева
byte F=7;   //Символ F, сверху слева
byte G=8;   //Символ G, центральный
byte Dp=9;  //Символ "точка"
byte D1=10; //Первый сегмент
byte D2=11; //Второй сегмент
byte D3=12; //Третий сегмент
byte D4=14; //Четвертый сегмент

byte H=18;   //Часы
byte M=00;   //Минуты
boolean S=true;    //Вкл/Откл светодиод секунд
unsigned long currentTime=0;
unsigned long loopTime=0;

byte H1=0;  //Часы, первая цифра
byte H2=0;  //Часы, вторая цифра
byte M1=0;  //Минуты, первая цифра
byte M2=0;  //Минуты, вторая цифра

void setup() {

  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(E, OUTPUT);
  pinMode(F, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(Dp, OUTPUT);
  pinMode(D1, OUTPUT);
  pinMode(D2, OUTPUT);
  pinMode(D3, OUTPUT);
  pinMode(D4, OUTPUT);

  digitalWrite(A, LOW);
  digitalWrite(B, LOW);
  digitalWrite(C, LOW);
  digitalWrite(D, LOW);
  digitalWrite(E, LOW);
  digitalWrite(F, LOW);
  digitalWrite(G, LOW);
  digitalWrite(Dp, LOW);
  digitalWrite(D1, HIGH);
  digitalWrite(D2, HIGH);
  digitalWrite(D3, HIGH);
  digitalWrite(D4, HIGH);

  currentTime = millis();       //считываем время, прошедшее с момента запуска программы
  loopTime = currentTime;
}

void loop() {
 
  H1=H/10;
  H2=H-(H1*10);
  M1=M/10;
  M2=M-(M1*10);

  currentTime = millis();                           //считываем время, прошедшее с момента запуска программы
  if(currentTime >= (loopTime + 1000)){
    S = !S;                                         //вкл/откл светодиод     
  }
  loopTime = currentTime;                           //в loopTime записываем новое значение

  digitalWrite(D1, LOW);
  outd(H1);
  digitalWrite(D1, HIGH);
 
  digitalWrite(D2, LOW);
  outd(H2);
  if (S) { digitDp(); }
  digitalWrite(D2, HIGH);
 
  digitalWrite(D3, LOW);
  outd(M1);
  digitalWrite(D3, HIGH);
 
  digitalWrite(D4, LOW);
  outd(M2);
  digitalWrite(D4, HIGH);
 
}

void outd(byte T){
   switch (T) {
    case 0:
      digit0();
    break;
    case 1:
      digit1();
    break;
    case 2:
      digit2();
    break;
    case 3:
      digit3();
    break;
    case 4:
      digit4();
    break;
    case 5:
      digit5();
    break;
    case 6:
      digit6();
    break;
    case 7:
      digit7();
    break;
    case 8:
      digit8();
    break;
    case 9:
      digit9();
    break;
}
  }
void digit1() {
  digitalWrite(B, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
}
void digit2() {
  digitalWrite(A, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(E, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(G, HIGH);
  digitalWrite(G, LOW);
}
void digit3() {
  digitalWrite(A, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(G, HIGH);
  digitalWrite(G, LOW);
}
void digit4() {
  digitalWrite(B, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(G, HIGH);
  digitalWrite(G, LOW);
}
void digit5() {
  digitalWrite(A, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(G, HIGH);
  digitalWrite(G, LOW);
}
void digit6() {
  digitalWrite(A, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(E, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(F, LOW);
}
void digit7() {
  digitalWrite(A, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
}
void digit8() {
  digitalWrite(A, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(E, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(G, HIGH);
  digitalWrite(G, LOW);
}
void digit9() {
  digitalWrite(A, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(G, HIGH);
  digitalWrite(G, LOW);
}
void digit0() {
  digitalWrite(A, HIGH);
  digitalWrite(A, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(E, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(F, LOW);
}
void digitDp() {
  digitalWrite(Dp, HIGH);
  digitalWrite(Dp, LOW);
}

a5021
Offline
Зарегистрирован: 07.07.2013

None пишет:
Почему-то не происходит инвертирование переменной S,

И не будет. Оператор "!" выполняет логическоую инверсию (true/false или 1/0), в то время, как вам нужна двоичная инверсия, за которую отвечает оператор "^".

None
Offline
Зарегистрирован: 15.01.2016

А разве тип boolean не является по факту одним битом, со значением 1 и 0?

И про ^ в справочнике ничего не сказано.

 

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

 

Блиин!! Вот я слепой, loopTime = currentTime; , нужно в о внутрь условия запрятать, иначе loopTime будет всегда ненамного отставать и условие не выполнится.

  currentTime = millis();                           //считываем время, прошедшее с момента запуска программы
  if(currentTime >= (loopTime + 1000)){
    S = !S;                                         //вкл/откл светодиод     
    loopTime = currentTime;                         //в loopTime записываем новое значение
    }
                             

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

У одного бита нет адреса. Минимально адресуемый объем информации - один байт. Соответственно, не может быть и переменной меньше байта.

Си - не Паскаль, здесь логические и целые типы не различаются. Поэтому компилятору нужно явно указывать, какой тип функции (арифметический или логический) нам нужен.

При двоичной инверсии 1 переходит в 254, а при логической - в 0. А 0 в 256 и 1 соответственно.

PS. Код не смотрел - только ответы на вопросы.

None
Offline
Зарегистрирован: 15.01.2016

andriano пишет:

Си - не Паскаль, здесь логические и целые типы не различаются. Поэтому компилятору нужно явно указывать, какой тип функции (арифметический или логический) нам нужен.

Не знаю ни того ни этого языка, в училище делфи проходили.

А можно ссылку, где подробно это рассказано?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015
None
Offline
Зарегистрирован: 15.01.2016

Я тут, в ожидании часов точного времени, набросал код использующий в качестве таймера функцию millis(), с выводом в сериал, и увидел, что ход достаточно точен, всегда кратен 1000. Учитывая, что функция обнуляется раз в 50 дней, получается довольно точный ход, с отставанием на одну секунду в 50 дней. Которое легко компенсировать.

То есть, можно сделать достаточно точный ход без внешних часов, главное обеспечить бесперебойным питанием?

None
Offline
Зарегистрирован: 15.01.2016

Вот такое чудо я наваял, прошу раскритиковать.

byte A=2;   //Символ A, сверху
byte B=3;   //Символ B, сверху справо
byte C=4;   //Символ C, снизу справо
byte D=5;   //Символ D, нижний
byte E=6;   //Символ E, снизу слева
byte F=7;   //Символ F, сверху слева
byte G=8;   //Символ G, центральный
byte Dp=9;  //Символ "точка"
byte D1=10; //Первый сегмент
byte D2=11; //Второй сегмент
byte D3=12; //Третий сегмент
byte D4=14; //Четвертый сегмент

byte H=0;   //Часы
byte M=0;   //Минуты
byte S=0;   //Секунды
byte Day=0;   //Дни, для компенсации отставания
bool Tik=true;    //Вкл/Откл светодиод секунд
bool Button1=0;    //антидребезг кнопки 1
bool Button2=0;    //антидребезг кнопки 2
int sensorValue=512;  //сенсор двух кнопок
unsigned long currentTime=0;
unsigned long loopTime=0;

byte H1=0;  //Часы, первая цифра
byte H2=0;  //Часы, вторая цифра
byte M1=0;  //Минуты, первая цифра
byte M2=0;  //Минуты, вторая цифра

void setup() {

  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(E, OUTPUT);
  pinMode(F, OUTPUT);
  pinMode(G, OUTPUT);
  pinMode(Dp, OUTPUT);
  pinMode(D1, OUTPUT);
  pinMode(D2, OUTPUT);
  pinMode(D3, OUTPUT);
  pinMode(D4, OUTPUT);

  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
  digitalWrite(Dp, HIGH);
  digitalWrite(D1, LOW);
  digitalWrite(D2, LOW);
  digitalWrite(D3, LOW);
  digitalWrite(D4, LOW);

  currentTime = millis();       //считываем время, прошедшее с момента запуска программы
  loopTime = currentTime;

}

void loop() {

  sensorValue = analogRead(A1);
  
  H1=H/10;
  H2=H-(H1*10);
  M1=M/10;
  M2=M-(M1*10);

  if(S==60){
    M++;
    S=0;
  }

  if(M==60){
    H++;
    M=0;
  }

  if(H==24){
    Day++;
    H=0;
  }

  if(Day==50){
    S++;
    Day=0;
  }

  if((sensorValue <= 300) && (Button1 == false)){   //Если нажата кнопка 1, замыкающая резистор 10К между выводом и землей, и флаг равен 0
    Button1 = true;
    M++;                  //Добавляем минуту
  }

  if((sensorValue > 300) && (Button1 == true)){
    Button1 = false;
  }

  if((sensorValue >= 700) && (Button2 == false)){   //Если нажата кнопка 2, замыкающая резистор 10К между выводом и плюсом, и флаг равен 0
    Button2 = true;
    H++;                  //Добавляем час
  }

  if((sensorValue < 700) && (Button2 == true)){
    Button2 = false;
  }

  currentTime = millis();                           //считываем время, прошедшее с момента запуска программы
  if(currentTime >= (loopTime + 1000)){
    loopTime = currentTime;                         //в loopTime записываем новое значение
    Tik = !Tik;                                     //вкл/откл светодиод     
    S++;
    }

  digitalWrite(D1, HIGH);
  outd(H1);
  digitalWrite(D1, LOW);
  
  digitalWrite(D2, HIGH);
  outd(H2);
  if (Tik) { digitDp(); }
  digitalWrite(D2, LOW);
  
  digitalWrite(D3, HIGH);
  outd(M1);
  digitalWrite(D3, LOW);
  
  digitalWrite(D4, HIGH);
  outd(M2);
  digitalWrite(D4, LOW);
  
}

void outd(byte T){
   switch (T) {
    case 0:
      digit0();
    break;
    case 1:
      digit1();
    break;
    case 2:
      digit2();
    break;
    case 3:
      digit3();
    break;
    case 4:
      digit4();
    break;
    case 5:
      digit5();
    break;
    case 6:
      digit6();
    break;
    case 7:
      digit7();
    break;
    case 8:
      digit8();
    break;
    case 9:
      digit9();
    break;
}
  }
void digit1() {
  digitalWrite(B, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
}
void digit2() {
  digitalWrite(A, LOW);
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(E, HIGH);
  digitalWrite(G, LOW);
  digitalWrite(G, HIGH);
}
void digit3() {
  digitalWrite(A, LOW);
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(G, LOW);
  digitalWrite(G, HIGH);
}
void digit4() {
  digitalWrite(B, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G, LOW);
  digitalWrite(G, HIGH);
}
void digit5() {
  digitalWrite(A, LOW);
  digitalWrite(A, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G, LOW);
  digitalWrite(G, HIGH);
}
void digit6() {
  digitalWrite(A, LOW);
  digitalWrite(A, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(E, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G, LOW);
  digitalWrite(G, HIGH);
}
void digit7() {
  digitalWrite(A, LOW);
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
}
void digit8() {
  digitalWrite(A, LOW);
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(E, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G, LOW);
  digitalWrite(G, HIGH);
}
void digit9() {
  digitalWrite(A, LOW);
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(F, HIGH);
  digitalWrite(G, LOW);
  digitalWrite(G, HIGH);
}
void digit0() {
  digitalWrite(A, LOW);
  digitalWrite(A, HIGH);
  digitalWrite(B, LOW);
  digitalWrite(B, HIGH);
  digitalWrite(C, LOW);
  digitalWrite(C, HIGH);
  digitalWrite(D, LOW);
  digitalWrite(D, HIGH);
  digitalWrite(E, LOW);
  digitalWrite(E, HIGH);
  digitalWrite(F, LOW);
  digitalWrite(F, HIGH);
}
void digitDp() {
  digitalWrite(Dp, LOW);
  digitalWrite(Dp, HIGH);
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. Сэру известно о существовании такой конструкции как оператор цикла?

2. Крайне любопытно, проверялось ли это "в железе". Мне почему-то кажется, что это работать не будет (по крайней мере так, как хотелось бы автору).

None
Offline
Зарегистрирован: 15.01.2016

1. Известно. Чем это поможет? Хотя, когда буду делать вольтметр, измеряющий напряжение резервной баттареи, думаю загнать в цикл посегметную индикацию, или вывести её так же в отдельную функцию. Пока не решил, как будет проще.

2. Работает, вот на столе лежит, хотя антидребезг, бывает, "прощелкивает", думаю как улучшить. Delay использовать не хочу, думаю на millis повлияет. Присматриваюсь к аппаратным решениям в виде связки кондера и резистора.

 

PS:

Это, пока, для меня слишком сложно, думаю в будущем дорасту.

PPS: Хотя аналога GOTO не хватает.