Использую 7seg 3 digit BA56-12GWA интересует способы его подключения

savdm
Offline
Зарегистрирован: 03.02.2015

1. Это через один 74HC595 (так он у меня сейчас работает) и три пина(у индикатора всего 12 ног) (динамический)

есть проблема, что с терморезистора даются чувствительные данные и меня раздражает, что плавает десятая доля температуры. Выглядит так как буд-то горят все сегменты, но когда "устаканилась" температура всё хорошо вроде бы:)

Думаю  попробовать средними значениями помочь - но кажется не поможет.

Возможно другой способ подключения посоветуете? Два 74HC595?Из Datasheet индикатора

bwn
Offline
Зарегистрирован: 25.08.2014

А уменьшить частоту вывода данных?

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

При динамической индикации обычно один разряд индикатора отображается порядка 5 мс (если дольше то будет мерцание). Т.е. три цифры отобразятся за 15 мс и если на каждом таком цикле значение изменяется то и будет видимость что горят все сегменты. А правильно надо делать как то так:

    value = // значение температуры
    unsigned long tt = millis();
    while ( (millis() - tt) < 500 ) {
      DisplayNumber(value);
    }

Т.е. 0,5 сек будет отображаться одно значение. Время можно подобрать в зависимости от желаемой динамики.

bwn
Offline
Зарегистрирован: 25.08.2014

Господа, объясните вы мне, где происходят такие процессы, которые нуждаются в визуальном контроле температуры каждые 0,5 секунды и чаще???? От для меня это загадка.

savdm
Offline
Зарегистрирован: 03.02.2015

Alex_Sk пишет:

При динамической индикации обычно один разряд индикатора отображается порядка 5 мс (если дольше то будет мерцание). Т.е. три цифры отобразятся за 15 мс и если на каждом таком цикле значение изменяется то и будет видимость что горят все сегменты. А правильно надо делать как то так:

    value = // значение температуры
    unsigned long tt = millis();
    while ( (millis() - tt) < 500 ) {
      DisplayNumber(value);
    }

Т.е. 0,5 сек будет отображаться одно значение. Время можно подобрать в зависимости от желаемой динамики.

Подчистил скетч от ненужного, не совсем понимаю, где эта задержка будет находиться?

#include <math.h>
// DS отвечает за поток битов(данные). На Схеме 595 пин 14
#define DATA_PIN 4
//STCP отвечает за так называемое защелкивание. Когда мы все свои биты передали, посылаем сигнал, что окончили передачу. На Схеме 595 пин 12
#define LATCH_PIN 3
// SHCP отвечает за ШИМ. Когда 1 из данных забирается бит, 0 пропускается.Синхронизация потока. На Схеме 595 пин 11
#define CLOCK_PIN 2
const int digitPins[3] = {
  52,51,50}; //Массив пинов. Выбрал произвольные кониакты у меня Мега
int8_t Disp[3]={
  0};// задается тип int8_t чтобы к нам ничего, кроме набора бит не попало.
int Value;
int i = 0;
#define ledPin1   22
#define ledPin2   23
double  TempRes; // Температура с терморезистора
byte segments[10] = {
B00111111, //0
B00000110, //1
B01011011, //2
B01001111, //3
B01100110, //4
B01101101, //5
B01111101, //6
B00000111, //7
B01111111, //8
B01101111 //9
}; 


void setup()
{
  Serial.begin(115200);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  for(byte j=0;j<3;j++)pinMode(digitPins[j],OUTPUT); //цикл - назначаем всем режим выход из нашего массива пинов
  pinMode(DATA_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
}

void printInd1()
{
for(byte d=0; d<3; d++) digitalWrite(digitPins[d], LOW);
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, B11111111);
digitalWrite(LATCH_PIN, HIGH);
delayMicroseconds(100); 
digitalWrite(digitPins[i], HIGH);
digitalWrite(LATCH_PIN, LOW); 
if(i==1){
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, ~(segments[Disp[i]] | B10000000));//print the decimal point on the 3rd digit
}
else
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, ~segments[Disp[i]]); 
digitalWrite(LATCH_PIN, HIGH);
  i++;
  if(i > 2) i=0;
}

double Steinhart (int value) {
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double B = 3988.0; // Параметр конкретного типа термистора (из datasheet)
   TempRes = (1.0 / (1.0 / (B)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0; // 10KOm - R_25
Value=TempRes *10;
//Выводим значение отсрочки срабатывания таймера на дисплей
Disp[0] = (Value/100)%10; //десятки
Disp[1] = (Value/10)%10;//единицы
Disp[2] = Value%10; //десятые


 //Функция для отображения на индикаторе
   printInd1(); 

  return TempRes;
}
void loop()
{
  Steinhart(analogRead(1));
}

 

savdm
Offline
Зарегистрирован: 03.02.2015

http://youtu.be/gque6VXJlFY

вот записал как это происходит, лучше не получилось:(

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

savdm пишет:

Подчистил скетч от ненужного, не совсем понимаю, где эта задержка будет находиться?

double Steinhart (int value) {
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double B = 3988.0; // Параметр конкретного типа термистора (из datasheet)
   TempRes = (1.0 / (1.0 / (B)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0; // 10KOm - R_25
Value=TempRes *10;
//Выводим значение отсрочки срабатывания таймера на дисплей
Disp[0] = (Value/100)%10; //десятки
Disp[1] = (Value/10)%10;//единицы
Disp[2] = Value%10; //десятые


 //Функция для отображения на индикаторе
   unsigned long tt = millis();
    while ( (millis() - tt) < 500 ) {
      printInd1();
    }    

  return TempRes;
}

Как-то так должно быть.

Вот только не понял куда возвращает эта функция значение TempRes?

savdm
Offline
Зарегистрирован: 03.02.2015

Alex_Sk пишет:

Вот только не понял куда возвращает эта функция значение TempRes?

там дальше используется для сравнения, убрал лишний код;)

savdm
Offline
Зарегистрирован: 03.02.2015

Alex_Sk пишет:

savdm пишет:

Подчистил скетч от ненужного, не совсем понимаю, где эта задержка будет находиться?

double Steinhart (int value) {
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double B = 3988.0; // Параметр конкретного типа термистора (из datasheet)
   TempRes = (1.0 / (1.0 / (B)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0; // 10KOm - R_25
Value=TempRes *10;
//Выводим значение отсрочки срабатывания таймера на дисплей
Disp[0] = (Value/100)%10; //десятки
Disp[1] = (Value/10)%10;//единицы
Disp[2] = Value%10; //десятые


 //Функция для отображения на индикаторе
   unsigned long tt = millis();
    while ( (millis() - tt) < 500 ) {
      printInd1();
    }    

  return TempRes;
}

Как-то так должно быть.

Вот только не понял куда возвращает эта функция значение TempRes?

очень сильно упала яркость, через нпн транзисторы подключить?

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

Может слишком быстро или слишком медленно на 595-ю данные гонятся?

Зачем вообще 74HC595 если индикатор всего 3-разрядный и аж целая Мега используется? 11 цифровых пинов жалко? Мне на 4-разрядный хватало Про Мини + 4 транзистора на общие аноды/катоды.

savdm
Offline
Зарегистрирован: 03.02.2015

Alex_Sk пишет:

Может слишком быстро или слишком медленно на 595-ю данные гонятся?

Зачем вообще 74HC595 если индикатор всего 3-разрядный и аж целая Мега используется? 11 цифровых пинов жалко? Мне на 4-разрядный хватало Про Мини + 4 транзистора на общие аноды/катоды.

Целевая будет ATTINY 84,  а у неё всего 14 ног. 

Подключение вот такое... как на схеме

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

Нормальная вроде схема. Я в программе не увидел задания делителя частоты для SPI поэтому shiftOut() может выполняться с тактовой до 4МГц. А в функции PrintInd1() есть несоответствие схеме и вообще вроде накосячено. В общем цикле перебираются разряды, при этом на выбранный пин выводится низкий уровень, а по схеме должен высокий. Для каждого разряда зачем-то выводятся сегменты от всех трех цифр. Плюс задержка на 100 мкс при погашенном индикаторе (в 595-ю задвинуты все единицы) а после того как задвигается выводимая цифра задержки нет, сразу переход к следующей. Т.е. в каждый разряд выводятся с большой частотой три цифры с паузой 100 мкс между разрядами. Время когда светятся сегменты значительно меньше паузы. Поэтому и яркость маленькая. А из-за того что в каждом разряде по три цифры одновременно все сегменты и горят.

savdm
Offline
Зарегистрирован: 03.02.2015

Alex_Sk пишет:

Нормальная вроде схема. Я в программе не увидел задания делителя частоты для SPI поэтому shiftOut() может выполняться с тактовой до 4МГц. А в функции PrintInd1() есть несоответствие схеме и вообще вроде накосячено. В общем цикле перебираются разряды, при этом на выбранный пин выводится низкий уровень, а по схеме должен высокий. Для каждого разряда зачем-то выводятся сегменты от всех трех цифр. Плюс задержка на 100 мкс при погашенном индикаторе (в 595-ю задвинуты все единицы) а после того как задвигается выводимая цифра задержки нет, сразу переход к следующей. Т.е. в каждый разряд выводятся с большой частотой три цифры с паузой 100 мкс между разрядами. Время когда светятся сегменты значительно меньше паузы. Поэтому и яркость маленькая. А из-за того что в каждом разряде по три цифры одновременно все сегменты и горят.

http://www.instructables.com/id/Temperature-Displayed-on-4-Digit-7-segment-common/

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

 

Нужно использовать http://arduino.ru/Reference/Library/SPI ?

 

Вся яркость пропадает если добавить строки

	   unsigned long tt = millis();
	    while ( (millis() - tt) < 500 ) {
	      printInd1();
	    } 

Как же верно реализовать?

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

Так происходит от непонимания принципа работы динамической индикации. А советы не помогают от того, что в коде каша.

#define DATA_PIN 4
#define LATCH_PIN 3
#define CLOCK_PIN 2

const byte digitPins[3] = {52,51,50}; 
byte disp[3];

void setup()
{
  for(byte i = 0; i < 3; i++) pinMode(digitPins[i], OUTPUT); 
  pinMode(DATA_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
}

void loop()
{
  Steinhart();
  Display();
}



void Steinhart() 
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 500) return;
  pre_millis = millis();
  
  int value = analogRead(1);
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double TempRes = (1.0 / (1.0 / (3988.0)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0;
  value = TempRes * 10;
  disp[0] = (value/100)%10; //десятки
  disp[1] = (value/10)%10;//единицы
  disp[2] = value%10; //десятые
}


const byte segments[10] = {
  B00111111, //0
  B00000110, //1
  B01011011, //2
  B01001111, //3
  B01100110, //4
  B01101101, //5
  B01111101, //6
  B00000111, //7
  B01111111, //8
  B01101111  //9
}; 

void Display()
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 5) return;
  pre_millis = millis();
  
  for(byte d = 0; d < 3; d++) digitalWrite(digitPins[d], LOW);
  
  digitalWrite(LATCH_PIN, LOW); 
  byte out = 0;
  static byte digit = 0;
  if(digit == 1) out = ~(segments[disp[digit]] | B10000000);
  else out = ~segments[disp[digit]];
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, out); 
  digitalWrite(LATCH_PIN, HIGH);
  
  digitalWrite(digitPins[digit], HIGH);
  
  digit++;
  if(digit > 2) digit = 0;
}

Так же на анодах должны стоять PNP транзисторы, а не NPN.

savdm
Offline
Зарегистрирован: 03.02.2015

maksim пишет:

Так происходит от непонимания принципа работы динамической индикации. А советы не помогают от того, что в коде каша.

#define DATA_PIN 4
#define LATCH_PIN 3
#define CLOCK_PIN 2

const byte digitPins[3] = {52,51,50}; 
byte disp[3];

void setup()
{
  for(byte i = 0; i < 3; i++) pinMode(digitPins[i], OUTPUT); 
  pinMode(DATA_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
}

void loop()
{
  Steinhart();
  Display();
}



void Steinhart() 
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 500) return;
  pre_millis = millis();
  
  int value = analogRead(1);
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double TempRes = (1.0 / (1.0 / (3988.0)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0;
  value = TempRes * 10;
  disp[0] = (value/100)%10; //десятки
  disp[1] = (value/10)%10;//единицы
  disp[2] = value%10; //десятые
}


const byte segments[10] = {
  B00111111, //0
  B00000110, //1
  B01011011, //2
  B01001111, //3
  B01100110, //4
  B01101101, //5
  B01111101, //6
  B00000111, //7
  B01111111, //8
  B01101111  //9
}; 

void Display()
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 5) return;
  pre_millis = millis();
  
  for(byte d = 0; d < 3; d++) digitalWrite(digitPins[d], LOW);
  
  digitalWrite(LATCH_PIN, LOW); 
  byte out = 0;
  static byte digit = 0;
  if(digit == 1) out = ~(segments[disp[digit]] | B10000000);
  else out = ~segments[disp[digit]];
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, out); 
  digitalWrite(LATCH_PIN, HIGH);
  
  digitalWrite(digitPins[digit], HIGH);
  
  digit++;
  if(digit > 2) digit = 0;
}

Так же на анодах должны стоять PNP транзисторы, а не NPN.

 

Спасибо, сейчас проверю. Полнейшая каша:(

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

И если делаете готовое устройство, то лучше возьмите ATMEGA8 и избавьтесь от сдвигового регистра.
Так же запитайте все это дело не от 5 вольт, а от 3,0 - 3,3 вольта и тогда токоограничительные резисторы на катодах будут не нужны.

savdm
Offline
Зарегистрирован: 03.02.2015
#include <math.h>
// DS отвечает за поток битов(данные). На Схеме 595 пин 14
#define DATA_PIN 4
//STCP отвечает за так называемое защелкивание. Когда мы все свои биты передали, посылаем сигнал, что окончили передачу. На Схеме 595 пин 12
#define LATCH_PIN 3
// SHCP отвечает за ШИМ. Когда 1 из данных забирается бит, 0 пропускается.Синхронизация потока. На Схеме 595 пин 11
#define CLOCK_PIN 2
const int digitPins[3] = {32,31,30}; //Массив пинов. Выбрал произвольные кониакты у меня Мега
int8_t Disp[3]={0};// задается тип int8_t чтобы к нам ничего, кроме набора бит не попало.
int Value;
int i = 0;
int flag = 0;//0 - не нажата ни одна, 1 - нажата одна
int regim ;
//unsigned long previousMillis = 0;//отсечка
//unsigned long time;
int TimePush = 2000;
#define ledPin1   22
#define ledPin2   23
byte Temp1 = 20; ////Температура Первого диапазона
byte Temp2 = 28; //Температура Второго диапазона
double  TempRes; // Температура с терморезистора
unsigned long previousMillis = 0;
const long interval = 25000;
unsigned long delta;
byte segments[10] = {
B00111111, //0
B00000110, //1
B01011011, //2
B01001111, //3
B01100110, //4
B01101101, //5
B01111101, //6
B00000111, //7
B01111111, //8
B01101111 //9
};
void setup()
{
//  Serial.begin(115200);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  for(byte j=0;j<3;j++)pinMode(digitPins[j],OUTPUT); //цикл - назначаем всем режим выход из нашего массива пинов
  pinMode(DATA_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
}

void printInd()
{
for(byte d=0; d<3; d++) digitalWrite(digitPins[d], LOW);
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, B11111111);
digitalWrite(LATCH_PIN, HIGH);
//delayMicroseconds(100);
digitalWrite(digitPins[i], HIGH);
digitalWrite(LATCH_PIN, LOW);
if(i==1){
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, ~(segments[Disp[i]] | B10000000));//print the decimal point on the 3rd digit
}
else
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, ~segments[Disp[i]]);
digitalWrite(LATCH_PIN, HIGH);
  i++;
  if(i > 2) i=0;
}
double Steinhart (int value) {
double Vin = 5.0; // напряжение питания
double voltage = value * Vin / 1023;
double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
double B = 3988.0; // Параметр конкретного типа термистора (из datasheet)
TempRes = (1.0 / (1.0 / (B)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0; // 10KOm - R_25
Value=TempRes*10 ;
//Выводим значение отсрочки срабатывания таймера на дисплей
Disp[0] = (Value/100)%10; //десятки
Disp[1] = (Value/10)%10;//единицы
Disp[2] = Value%10; //десятые
unsigned long tt = millis();
 while ( (millis() - tt) < 500 ) {
   printInd();
 }
  return TempRes;
}

void click()
{
	int VRes = analogRead(0); // значение с аналог пина
	if (flag == 0 && VRes<300 && VRes>0) // нажата ли кнопка 1 +
	{
		previousMillis = millis(); // когда нажата
		flag = 1; // состояние что нажата
	}
	if (flag == 1 && VRes<300 && VRes>0 && ((millis() - previousMillis) >= TimePush))flag = 2;// выполняем первый режим работы прибавление 5 ед.
	if (VRes > 1000 && flag > 0)
	{
		// отпустили кнопку смотрим сколько её держали
		switch (flag)
		{
		case 1:
			regim = 2; // короткое нажатие  //прибавление единицы
			break;
		case 2:
			regim = 1; // длинное нажатие  //прибавление 5 единиц
			break;
		}
		flag = 3; //кнопка отжата
	}

	//Два других режима по аналогии
	if (flag1 == 0 && VRes > 400 && VRes < 600) // нажата ли кнопка 2 -
	{
		previousMillis1 = millis();  // когда нажата
		flag1 = 1; // состояние что нажата
	}
	if (flag1 == 1 && VRes > 400 && VRes < 600 && ((millis() - previousMillis1) >= TimePush))flag1 = 2;// третий режим - отнимаем 5 ед.
	if (VRes > 1000 && flag1 > 0)
	{
		// отпустили кнопку смотрим сколько её держали
		switch (flag1)
		{
		case 1:
			regim = 4; // короткое нажатие  //прибавление единицы
			break;
		case 2:
			regim = 3; // длинное нажатие  //прибавление 5 единиц
			break;
		}
		flag1 = 3; //кнопка отжата
	}
switch (regim)
	{
	case 1:
		Value += 5;
		regim = 0;
		flag = 0;
		break;
	case 2:
		Value++;
		regim = 0;
		flag = 0;
		break;
	case 3:
		Value -= 5;
		regim = 0;
		flag1 = 0;
		break;
	case 4:
		Value--;
		regim = 0;
		flag1 = 0;
		break;
	}
if (flag1==3&&flag==0||flag1==0&&flag==3) //Защита при одновременном нажатии двух кнопок
{
  flag1=0;
  flag=0;
}
}

void releTime1(){

  if((digitalRead(ledPin1)==HIGH&&digitalRead(ledPin2)==HIGH)||digitalRead(ledPin1)==LOW&&digitalRead(ledPin2)==LOW){
    digitalWrite(ledPin1,HIGH);
    digitalWrite(ledPin2,LOW);
    previousMillis=millis();
    delta = interval-millis()+previousMillis;
  }
  else if (digitalRead(ledPin1)==HIGH&&digitalRead(ledPin2)==LOW&&(previousMillis + delta)<= millis()){
    digitalWrite(ledPin1,LOW);
    digitalWrite(ledPin2,HIGH);
    previousMillis = millis();
  }
  else if (digitalRead(ledPin1)==LOW&&digitalRead(ledPin2)==HIGH&&(previousMillis + delta)<= millis()){
    digitalWrite(ledPin1,HIGH);
    digitalWrite(ledPin2,LOW);
    previousMillis = millis();
  }
}
void releTime2(){
  if (digitalRead(ledPin1)==LOW||digitalRead(ledPin2)==LOW||digitalRead(ledPin1)==LOW&&digitalRead(ledPin2)==LOW){
    digitalWrite(ledPin1,HIGH);
    digitalWrite(ledPin2,HIGH);
  }
}
void releTime3(){
  if (digitalRead(ledPin1)==HIGH||digitalRead(ledPin2)==HIGH||digitalRead(ledPin1)==HIGH||digitalRead(ledPin2)==HIGH){
    digitalWrite(ledPin1,LOW);
    digitalWrite(ledPin2,LOW);
  }
}
void loop()
{
  click();
  while (Temp1<Steinhart(analogRead(1)) && Temp2>Steinhart(analogRead(1)))releTime1();
  while (Temp1<Steinhart(analogRead(1)) && Temp2<Steinhart(analogRead(1)))releTime2();
  while (Temp1>Steinhart(analogRead(1)) && Temp2>Steinhart(analogRead(1)))releTime3();
}



Вот так выглядит полный скетч

savdm
Offline
Зарегистрирован: 03.02.2015

maksim пишет:

И если делаете готовое устройство, то лучше возьмите ATMEGA8 и избавьтесь от сдвигового регистра.
Так же запитайте все это дело не от 5 вольт, а от 3,0 - 3,3 вольта и тогда токоограничительные резисторы на катодах будут не нужны.

Как раз об этом думал от 3.3 запитать. Там входное на сегменты 2.5 и на цифры 5.0

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

Чуть завышенный ток при динамической индикации некритичен.

savdm
Offline
Зарегистрирован: 03.02.2015

maksim пишет:

И если делаете готовое устройство, то лучше возьмите ATMEGA8 и избавьтесь от сдвигового регистра.

Attiny84 уже лежит:) Мне немножко раньше нужно было думать об этом - хотел малой кровью, а выходит проблемно.

savdm
Offline
Зарегистрирован: 03.02.2015

Спасибо, ваш пример работает отлично, есть небольшое мирцание, но это некритично.

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

Уменьшите задержку засветки с 5, наример, до 2 в 57 строке.

     if(millis()-pre_millis < 2) return;

 

savdm
Offline
Зарегистрирован: 03.02.2015

maksim пишет:

Уменьшите задержку засветки с 5, наример, до 2 в 57 строке.

     if(millis()-pre_millis < 2) return;

 

Так и сделал, до 3.

 

Теперь надо всё в солянку вставить))

savdm
Offline
Зарегистрирован: 03.02.2015

maksim пишет:

Полный скетч

#include <Arduino.h>
#include <math.h>
// DS отвечает за поток битов(данные). На Схеме 595 пин 14
#define DATA_PIN 4
//STCP отвечает за так называемое защелкивание. Когда мы все свои биты передали, посылаем сигнал, что окончили передачу. На Схеме 595 пин 12
#define LATCH_PIN 3
// SHCP отвечает за ШИМ. Когда 1 из данных забирается бит, 0 пропускается.Синхронизация потока. На Схеме 595 пин 11
#define CLOCK_PIN 2
const int digitPins[3] = {32,31,30}; //Массив пинов.На цифры сегмента 5в
int8_t disp[3]={0};// задается тип int8_t чтобы к нам ничего, кроме набора бит не попало.
int Value;
int i = 0;
int flag = 0,flag1 = 0;//0 - не нажата ни одна, 1 - нажата одна
int regim ;
//unsigned long previousMillis = 0;//отсечка
//unsigned long time;
int TimePush = 2000;
#define ledPin1   22
#define ledPin2   23
double  TempRes;
byte Temp1 = 20; ////Температура Первого диапазона
byte Temp2 = 28; //Температура Второго диапазона
unsigned long previousMillis = 0,previousMillis1 = 0;
const long interval = 25000;
unsigned long delta;
const byte segments[10] = {
  B00111111, //0
  B00000110, //1
  B01011011, //2
  B01001111, //3
  B01100110, //4
  B01101101, //5
  B01111101, //6
  B00000111, //7
  B01111111, //8
  B01101111  //9
};
double Steinhart()
{
  static uint32_t pre_millis1 = 0;
  if(millis()-pre_millis1 < 400) return;
  pre_millis1 = millis();

  int value = analogRead(1);
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double TempRes = (1.0 / (1.0 / (3988.0)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0;
  value = TempRes * 10;
  disp[0] = (value/100)%10; //десятки
  disp[1] = (value/10)%10;//единицы
  disp[2] = value%10; //десятые
  Display();
  return TemRes;
}
void Display()
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 3) return;
  pre_millis = millis();

  for(byte d = 0; d < 3; d++) digitalWrite(digitPins[d], LOW);

  digitalWrite(LATCH_PIN, LOW);
  byte out = 0;
  static byte digit = 0;

  if(digit == 1) out = ~(segments[disp[digit]] | B10000000);
  else out = ~segments[disp[digit]];

  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, out);

  digitalWrite(LATCH_PIN, HIGH);

  digitalWrite(digitPins[digit], HIGH);
  digit++;
  if(digit > 2) digit = 0;
}
void releTime1()
{
  if((digitalRead(ledPin1)==HIGH&&digitalRead(ledPin2)==HIGH)||digitalRead(ledPin1)==LOW&&digitalRead(ledPin2)==LOW){
    digitalWrite(ledPin1,HIGH);
    digitalWrite(ledPin2,LOW);
    previousMillis=millis();
    delta = interval-millis()+previousMillis;
  }
  else if (digitalRead(ledPin1)==HIGH&&digitalRead(ledPin2)==LOW&&(previousMillis + delta)<= millis()){
    digitalWrite(ledPin1,LOW);
    digitalWrite(ledPin2,HIGH);
    previousMillis = millis();
  }
  else if (digitalRead(ledPin1)==LOW&&digitalRead(ledPin2)==HIGH&&(previousMillis + delta)<= millis()){
    digitalWrite(ledPin1,HIGH);
    digitalWrite(ledPin2,LOW);
    previousMillis = millis();
  }
}
void releTime2()
{
  if (digitalRead(ledPin1)==LOW||digitalRead(ledPin2)==LOW||digitalRead(ledPin1)==LOW&&digitalRead(ledPin2)==LOW){
    digitalWrite(ledPin1,HIGH);
    digitalWrite(ledPin2,HIGH);
  }
}
void releTime3()
{
  if (digitalRead(ledPin1)==HIGH||digitalRead(ledPin2)==HIGH||digitalRead(ledPin1)==HIGH||digitalRead(ledPin2)==HIGH){
    digitalWrite(ledPin1,LOW);
    digitalWrite(ledPin2,LOW);
  }
}
void click()
{
	int VRes = analogRead(0); // значение с аналог пина
	if (flag == 0 && VRes<300 && VRes>0) // нажата ли кнопка 1 +
	{
		previousMillis = millis(); // когда нажата
		flag = 1; // состояние что нажата
	}
	if (flag == 1 && VRes<300 && VRes>0 && ((millis() - previousMillis) >= TimePush))flag = 2;// выполняем первый режим работы прибавление 5 ед.
	if (VRes > 1000 && flag > 0)
	{
		// отпустили кнопку смотрим сколько её держали
		switch (flag)
		{
		case 1:
			regim = 2; // короткое нажатие  //прибавление единицы
			break;
		case 2:
			regim = 1; // длинное нажатие  //прибавление 5 единиц
			break;
		}
		flag = 3; //кнопка отжата
	}

	//Два других режима по аналогии
	if (flag1 == 0 && VRes > 400 && VRes < 600) // нажата ли кнопка 2 -
	{
		previousMillis1 = millis();  // когда нажата
		flag1 = 1; // состояние что нажата
	}
	if (flag1 == 1 && VRes > 400 && VRes < 600 && ((millis() - previousMillis1) >= TimePush))flag1 = 2;// третий режим - отнимаем 5 ед.
	if (VRes > 1000 && flag1 > 0)
	{
		// отпустили кнопку смотрим сколько её держали
		switch (flag1)
		{
		case 1:
			regim = 4; // короткое нажатие  //прибавление единицы
			break;
		case 2:
			regim = 3; // длинное нажатие  //прибавление 5 единиц
			break;
		}
		flag1 = 3; //кнопка отжата
	}
switch (regim)
	{
	case 1:
		Value += 5;
		regim = 0;
		flag = 0;
		break;
	case 2:
		Value++;
		regim = 0;
		flag = 0;
		break;
	case 3:
		Value -= 5;
		regim = 0;
		flag1 = 0;
		break;
	case 4:
		Value--;
		regim = 0;
		flag1 = 0;
		break;
	}
if (flag1==3&&flag==0||flag1==0&&flag==3) //Защита при одновременном нажатии двух кнопок
{
  flag1=0;
  flag=0;
}
}
void setup()
{
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  for(byte j=0;j<3;j++)pinMode(digitPins[j],OUTPUT); //цикл - назначаем всем режим выход из нашего массива пинов
  pinMode(DATA_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
}

void loop()
{
  click();
  while (Temp1<Steinhart() && Temp2>Steinhart())releTime1();
  while (Temp1<Steinhart() && Temp2<Steinhart())releTime2();
  while (Temp1>Steinhart() && Temp2>Steinhart())releTime3();
}

Как быть с этим, чтобы возвратить значение??
 

double Steinhart()
{
  static uint32_t pre_millis1 = 0;
  if(millis()-pre_millis1 < 400) return;
  pre_millis1 = millis();

  int value = analogRead(1);
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double TempRes = (1.0 / (1.0 / (3988.0)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0;
  value = TempRes * 10;
  disp[0] = (value/100)%10; //десятки
  disp[1] = (value/10)%10;//единицы
  disp[2] = value%10; //десятые
  Display();
  return TemRes;
}

 

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

Вы опять намешали все в кучу. Оставьте Display(); там где она была, не надо ее засовывать в другие функции, она там работать не будет. Переменную TempRes сделайте глобальной.

savdm
Offline
Зарегистрирован: 03.02.2015

maksim пишет:

Вы опять намешали все в кучу. Оставьте Display(); там где она была, не надо ее засовывать в другие функции, она там работать не будет. Переменную TempRes сделайте глобальной.




double  TempRes;


void Steinhart()
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 400) return;

  pre_millis = millis();

  int value = analogRead(1);
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double TempRes = (1.0 / (1.0 / (3988.0)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0;
  value = TempRes * 10;
  disp[0] = (value/100)%10; //десятки
  disp[1] = (value/10)%10;//единицы
  disp[2] = value%10; //десятые
}
void Display()
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 3) return;
  pre_millis = millis();

  for(byte d = 0; d < 3; d++) digitalWrite(digitPins[d], LOW);

  digitalWrite(LATCH_PIN, LOW);
  byte out = 0;
  static byte digit = 0;

  if(digit == 1) out = ~(segments[disp[digit]] | B10000000);
  else out = ~segments[disp[digit]];

  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, out);

  digitalWrite(LATCH_PIN, HIGH);

  digitalWrite(digitPins[digit], HIGH);
  digit++;
  if(digit > 2) digit = 0;
}

void loop()
{
  click();
  Steinhart();
  Display();
  if (Temp1<TempRes && Temp2>TempRes)releTime1();
  if (Temp1<TempRes && Temp2<TempRes)releTime2();
  if (Temp1>TempRes && Temp2>TempRes)releTime3();
}

Правильно понимаю не while, a if надо?

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

Правильно. Только вот от циклов while(...) надо избавляться, иначе как только дойдет до этой части программа зависнет.

savdm
Offline
Зарегистрирован: 03.02.2015

maksim пишет:

Правильно. Только вот от циклов while(...) надо избавляться, иначе как только дойдет до этой части программа зависнет.

не while, a if надо. До этого использовали потому что были кратковременны включения светодиодов.

savdm
Offline
Зарегистрирован: 03.02.2015

Вот протестировал со льдом, всё, как нужно работает, буду теперь проверять. Спасибо Вам большое, что помогли. Еще паузу повысил до секунды  в  Steinhart(), иначе значение прыгает и выполняется условия реле(мигает)

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

Более оптимизировано:

const byte segments[10] = {
  B00111111, //0
  B00000110, //1
  B01011011, //2
  B01001111, //3
  B01100110, //4
  B01101101, //5
  B01111101, //6
  B00000111, //7
  B01111111, //8
  B01101111  //9
}; 

void Steinhart() 
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 500) return;
  pre_millis = millis();
  
  int value = analogRead(1);
  double Vin = 5.0; // напряжение питания
  double voltage = value * Vin / 1023;
  double r1 = voltage * 9740.0 / (Vin - voltage); // 10 кОм - подтягивающий резистор
  double TempRes = (1.0 / (1.0 / (3988.0)*log(r1 / 10000.0) + 1.0 / (273.0 + 25.0))) - 273.0;
  value = TempRes * 10;
  disp[0] = ~segments[(value/100)%10];              //десятки
  disp[1] = ~(segments[(value/10)%10] | B10000000); //единицы
  disp[2] = ~segments[value%10];                    //десятые
}


void Display()
{
  static uint32_t pre_millis = 0;
  if(millis()-pre_millis < 5) return;
  pre_millis = millis();
  
  for(byte d = 0; d < 3; d++) digitalWrite(digitPins[d], LOW);
  
  digitalWrite(LATCH_PIN, LOW); 
  static byte digit = 0;
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, disp[digit]); 
  digitalWrite(LATCH_PIN, HIGH);
  
  digitalWrite(digitPins[digit], HIGH);
  
  digit++;
  if(digit > 2) digit = 0;
}