Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить

Re: Нужна прошивка для подключения датчиков температуры ds18

Пт мар 31, 2017 16:11:38

krasdok писал(а):Не судите строго, я только учусь...

Ну что-ж тогда извините. я вас принял за человека ищущего простые пути, раз это не так то для начала разберитесь с протоколом 1wire , а потом проанализируйте любую библиотеку для работы с этим датчиком . И когда поймете вам не составит никакого труда самостоятельно вывести полученную температуру на дисплей.

Лично из моего опыта работы с этим датчиком - когда пытался проверять чексумму полученного от него скратчпада все глючило , на 100 чтений только одно проходило , когда просто перестал проверять и сразу обрабатывал данные все работало как часы и показывало правильную температуру, понятия не имею где я тогда накосячил но все-же.

Re: Нужна прошивка для подключения датчиков температуры ds18

Пт мар 31, 2017 18:46:28

acckyiboxxx писал(а):когда пытался проверять чексумму полученного от него скратчпада все глючило , на 100 чтений только одно проходило , когда просто перестал проверять и сразу обрабатывал данные все работало как часы и показывало правильную температуру
пока ходил к врачу - все время приходилось лечиться. перестал ходить - и сразу выздоровел.

нормально, чо

Re: Нужна прошивка для подключения датчиков температуры ds18

Пт мар 31, 2017 21:34:58

Вот от сюда пример взял http://radioparty.ru/prog-avr/program-c ... n2-ds18b20

Что есть датчик что нету всегда Y
if(OK_Flag == 1) // åñëè äàò÷èê íå îòâåòèë
{
// ñòàâèì ïðî÷åðêè âî âñåõ ðàçðÿäàõ
lcd_dat('N');
}
else
{
lcd_dat('Y');
}

Вот мой код (на экране)

#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>


#define RS PC0
#define EN PC1


int s = 0; // ïåðåìåííàÿ äëÿ õðàíåíèÿ ñåêóíä
int m = 0; // ïåðåìåííàÿ äëÿ õðàíåíèÿ ìèíóò
int z = 0; // ïåðåìåííàÿ äëÿ õðàíåíèÿ ÷àñû

//----------
char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x80, 0x40, 0x00};
volatile unsigned char segcounter = 0;
volatile int display1 = 0, display2 = 0, display3 = 0, display4 = 0;


unsigned char Temp_H = 0,Temp_L = 0,OK_Flag = 0,temp_flag;
/*** Èíèöèàëèçàöèÿ DS18B20 ***/
unsigned char DS18B20_init(void)
{
PORTD &= ~(1 << PD5); // óñòàíàâëèâàåì íèçêèé óðîâåíü
DDRD |= (1 << PD5);
_delay_us(490);
DDRD &= ~(1 << PD5);
_delay_us(68);
OK_Flag = (PIND & (1 << PD5)); // ëîâèì èìïóëüñ ïðèñóòñòâèÿ äàò÷èêà
// åñëè OK_Flag = 0 äàò÷èê ïîäêëþ÷åí, OK_Flag = 1 äàò÷èê íå ïîäêëþ÷åí
_delay_us(422);
return OK_Flag;
}
/*** Ôóíêöèÿ ÷òåíèÿ áàéòà èç DS18B20 ***/
unsigned char read_18b20(void)
{
unsigned char i;
unsigned char dat = 0;
for(i = 0;i < 8;i++)
{
DDRD |= (1 << PD5);
_delay_us(2);
DDRD &= ~(1 << PD5);
_delay_us(4);
dat = dat >> 1;
if(PIND & (1 << PD5))
{
dat |= 0x80;
}
_delay_us(62);
}
return dat;
}
/*** ôóíêöèÿ çàïèñè áàéòà â DS18B20 ***/
void write_18b20(unsigned char dat)
{
unsigned char i;
for(i = 0;i < 8;i++)
{
DDRD |= (1 << PD5);
_delay_us(2);
if(dat & 0x01)
{
DDRD &= ~(1 << PD5);
}
else
{
DDRD |= (1 << PD5);
}
dat = dat >> 1;
_delay_us(62);
DDRD &= ~(1 << PD5);
_delay_us(2);
}
}



// Ôóíêöèÿ çàïèñè êîìàíäû â ÆÊÈ
void lcd_com(unsigned char p)
{
PORTC &= ~(1 << RS); // RS = 0 (çàïèñü êîìàíä)
PORTC |= (1 << EN); // EN = 1 (íà÷àëî çàïèñè êîìàíäû â LCD)
PORTA &= 0x0F; PORTA |= (p & 0xF0); // Âûäåëÿåì ñòàðøèé íèáë
_delay_us(100);
PORTC &= ~(1 << EN); // EN = 0 (êîíåö çàïèñè êîìàíäû â LCD)
_delay_us(100);
PORTC |= (1 << EN); // EN = 1 (íà÷àëî çàïèñè êîìàíäû â LCD)
PORTA &= 0x0F; PORTA |= (p << 4); // Âûäåëÿåì ìëàäøèé íèáë
_delay_us(100);
PORTC &= ~(1 << EN); // EN = 0 (êîíåö çàïèñè êîìàíäû â LCD)
_delay_us(100);
}

// Ôóíêöèÿ çàïèñè äàííûõ â ÆÊÈ
void lcd_dat(unsigned char p)
{
PORTC |= (1 << RS)|(1 << EN); // RS = 1 (çàïèñü äàííûõ), EN - 1 (íà÷àëî çàïèñè êîìàíäû â LCD)
PORTA &= 0x0F; PORTA |= (p & 0xF0); // Âûäåëÿåì ñòàðøèé íèáë
_delay_us(100);
PORTC &= ~(1 << EN); // EN = 0 (êîíåö çàïèñè êîìàíäû â LCD)
_delay_us(100);
PORTC |= (1 << EN); // EN = 1 (íà÷àëî çàïèñè êîìàíäû â LCD)
PORTA &= 0x0F; PORTA |= (p << 4); // Âûäåëÿåì ìëàäøèé íèáë
_delay_us(100);
PORTC &= ~(1 << EN); // EN = 0 (êîíåö çàïèñè êîìàíäû â LCD)
_delay_us(100);
}

// Ôóíêöèÿ èíèöèàëèçàöèè ÆÊÈ
void lcd_init(void)
{
DDRC |= (1 << PC1)|(1 << PC0); // PC1, PC0 - âûõîäû
PORTC = 0x00;
DDRA = 0xFF; // ïîðò D - âûõîä
PORTA = 0x00;

_delay_ms(50); // Îæèäàíèå ãîòîâíîñòè ÆÊ-ìîäóëÿ

// Êîíôèãóðèðîâàíèå ÷åòûðåõðàçðÿäíîãî ðåæèìà
PORTA |= (1 << PA5);
PORTA &= ~(1 << PA4);

// Àêòèâèçàöèÿ ÷åòûðåõðàçðÿäíîãî ðåæèìà
PORTC |= (1 << EN);
PORTC &= ~(1 << EN);
_delay_ms(5);

lcd_com(0x28); // Øèíà 4 áèò, LCD - 2 ñòðîêè
lcd_com(0x08); // Ïîëíîå âûêëþ÷åíèå äèñïëåÿ
lcd_com(0x01); // Î÷èñòêà äèñïëåÿ
_delay_us(100);
lcd_com(0x06); // Ñäâèã êóðñîðà âïðàâî
_delay_ms(10);
lcd_com(0x0C); // Âêëþ÷åíèå äèñïëåÿ, êóðñîð íå âèäèì
}

ISR(TIMER1_COMPA_vect)
{

s++; // óâåëè÷èâàåì ïåðåìåííóþ êàæäóþ ñåêóíäó
if(s>59) // îáíóëÿåì ñåêóíäû ïîñëå 59
{
s=0;
m++;
}
if(m>59)
{
m=0;
z++;
}
if(z>59)
{
z=0;
}
TCNT1 = 0; //?????????? ????????? ???????? TCNT1


}



// Îñíîâíàÿ ïðîãðàììà
int main (void)
{


lcd_init(); // Èíèöèàëèçàöèÿ äèñïëåÿ

TCCR1A=0x00; //íàñòðîéêà òàéìåðà
TCCR1B=0x05;
TCNT1=0x00; //çäåñü óâåëè÷èâàþòñÿ òèêè
OCR1A=0x2dc7; //çàïèñûâàåì ÷èñëî â ðåãèñòð ñðàâíåíèÿ

TIMSK=0x10; //çàïóñêàåì òàéìåð
_delay_ms(50);

unsigned int tempint = 0,tempint1,tempint2,tempint3; // ïåðåìåííûå äëÿ öåëîãî çíà÷åíèÿ òåìïåðàòóðû
unsigned int temppoint = 0,temppoint1; // ïåðåìåííûå äëÿ äðîáíîãî çíà÷åíèÿ òåìïåðàòóðû

//sei();
while (1)
{
lcd_com(0x80); // Âûâîä â âåðõíþþ ëåâóþ ïîçèöèþ 1 ñòðîêè
lcd_dat(z/10+0x30); //âûâîä äåñÿòêîâ ÷àñîâ
lcd_dat(z%10+0x30); //âûâîä ÷àñîâ
lcd_dat(':');
lcd_dat(m/10+0x30); //âûâîä äåñÿòêîâ ìèíóò
lcd_dat(m%10+0x30); //âûâîä ìèíóò
lcd_dat(':');
lcd_dat(s/10+0x30); //âûâîä äåñÿòêîâ ñåêóíä
lcd_dat(s%10+0x30); //âûâîä ñåêóíä
if(OK_Flag == 1) // åñëè äàò÷èê íå îòâåòèë
{
// ñòàâèì ïðî÷åðêè âî âñåõ ðàçðÿäàõ
lcd_dat('N');
}
else
{
lcd_dat('Y');
}
DS18B20_init(); // èíèöèàëèçàöèÿ DS18B20

write_18b20(0xCC); // ïðîâåðêà êîäà äàò÷èêà
write_18b20(0x44); // çàïóñê òåìïåðàòóðíîãî ïðåîáðàçîâàíèÿ
_delay_ms(1000);
DS18B20_init(); // èíèöèàëèçàöèÿ DS18B20
write_18b20(0xCC); // ïðîâåðêà êîäà äàò÷èêà
write_18b20(0xBE); // ñ÷èòûâàåì ñîäåðæèìîå ÎÇÓ
Temp_L = read_18b20(); // ÷èòàåì ïåðâûå 2 áàéòà áëîêíîòà
Temp_H = read_18b20();
temp_flag = 1; // ôëàã çíàêà òåìïåðàòóðû ðàâåí 1(ïëþñ)
if(Temp_H &(1 << 3)) // ïðîâåðÿåì áèò çíàêà òåìïåðàòóðû íà ðàâåíñòâî åäèíèöå
{
signed int tmp;
temp_flag = 0; // ôëàã çíàêà ðàâåí 0(ìèíóñ)
tmp = (Temp_H << 8) | Temp_L;
tmp = -tmp;
Temp_L = tmp;
Temp_H = tmp >> 8;
}
tempint = ((Temp_H << 4) & 0x70)|(Temp_L >> 4); // âû÷èñëÿåì öåëîå çíà÷åíèå òåìïåðàòóðû
tempint1 = tempint % 1000 / 100;
tempint2 = tempint % 100 / 10;
tempint3 = tempint % 10;
temppoint = Temp_L & 0x0F; // âû÷èñëÿåì äðîáíîå çíà÷åíèå òåìïåðàòóðû
temppoint = temppoint * 625; // òî÷íîñòü òåìïåðàòóðû
temppoint1 = temppoint / 1000;
if(temp_flag == 0) // åñëè ôëàã çíàêà òåìïåðàòóðû ðàâåí 0, â ïåðâîì ðàçðÿäå ñòàâèì ìèíóñ
tempint1 = 11;
if(tempint1 < 1) // åñëè ïåðâàÿ öèôðà çíà÷åíèÿ òåìïåðàòóðû ìåíüøå 1, òî ãàñèì 1 ðàçðÿä èíäèêàòîðà
tempint1 = 12;
if(tempint1 == 12 && tempint2 < 1) // åñëè ïåðâàÿ öèôðà ïîãàøåíà è âòîðàÿ öèôðà çíà÷åíèÿ òåìïåðàòóðû ìåíüøå 1, òî ãàñèì 2 ðàçðÿä èíäèêàòîðà
tempint2 = 12;
if(tempint2 < 1 && temp_flag == 0) // åñëè âòîðàÿ öèôðà çíà÷åíèÿ òåìïåðàòóðû ìåíüøå 1 è çíàê ðàâåí "ìèíóñ", òî ãàñèì 2 ðàçðÿä èíäèêàòîðà
tempint2 = 12;
// âûâîäèì çíà÷åíèÿ íà äèñïëåé
display1 = tempint1;
display2 = tempint2;
display3 = tempint3;
display4 = temppoint1;
lcd_dat(tempint1);
lcd_dat(tempint2);
lcd_dat(tempint3);
}
}

Re: Нужна прошивка для подключения датчиков температуры ds18

Сб апр 01, 2017 02:06:25

ARV писал(а):пока ходил к врачу - все время приходилось лечиться. перестал ходить - и сразу выздоровел.

нормально, чо


ну вот пришел к "врачу", вот она функция проверки из того кода , что тут не так ?

Код:
uint8_t DALLAS_CRC(int show){
   reset_watchdog(); // СБРАСЫВАЕМ СТОРОЖЕВОЙ ТАЙМЕР
   uint8_t crc = 0; // СТАРТОВОЕ ЗНАЧЕНИЕ CRC
   for (uint8_t x = 0 ; x < 8 ; x++){ // В ЭТОМ ЦИКЛЕ ЧИТАЕМ CRC ДЛЯ ПЕРВЫХ 8-И БАЙТ БЛОКНОТА
      crc = crc ^ (DS_NOTEPAD[x]); // ДЛЯ НАЧАЛА НАЙДЕМ ИСКЛЮЧАЮЩЕЕ ИЛИ МЕЖДУ ТЕКУЩИМ ЗНАЧЕНИЕМ CRC И МЛАДШИМ БИТОМ ДАННЫХ
      for (uint8_t y = 0 ; y < 8 ; y++){
         if (crc & 0x01) { crc = (crc >> 1) ^ 0x8C; }
         else { crc >>= 1; }
      }
   }
   if (crc == DS_NOTEPAD[8] ) { // ЕСЛИ ПРИНЯТАЯ ОТ ДАТЧИКА И ПОДСЧИТАННАЯ CRC СОВПАЛИ
      DS18B20_FLAGS.crc_err = FALSE;
      return TRUE; // ВЕРНЕМ ИСТИНУ
   }
   else { // ИНАЧЕ ОТОБРАЗИМ ЮЗВЕРЮ НАДПИСЬ CR
      DS18B20_FLAGS.crc_err = TRUE;
      if(show) { display_crc(); }
      return FALSE; // НУ И НАКОНЕЦ ВЕРНЕМ ЛОЖЬ
   }
}

Re: Нужна прошивка для подключения датчиков температуры ds18

Сб апр 01, 2017 04:49:31

В том коде этой функции нет...

Добавлено after 8 minutes 52 seconds:
Re: Нужна прошивка для подключения датчиков температуры ds18b20
В модуле датчика между "+" и ногой данных стоит сопротивление плюс диод. Это нормально???
Везде только сопротивление для подтягивания +.
НО при любом подключение тишина

Добавлено after 4 minutes 43 seconds:
Re: Нужна прошивка для подключения датчиков температуры ds18b20
Пойду куплю оригинальный датчик.
Помогите код написать плиззз...Все в него уперлось...
Туплю...блин

Re: Нужна прошивка для подключения датчиков температуры ds18

Сб апр 01, 2017 06:37:51

krasdok, это не из вашего кода, у меня уцелел бэкап того проекта о котором писал выше и ARV раскритиковал , вот мне и стало интересно.

Re: Нужна прошивка для подключения датчиков температуры ds18

Сб апр 01, 2017 18:00:10

У меня atmega32 + DS18B20+lcd 1602 atmelstudio 4 пример рабочего кода у кого-нибудь есть???

Re: Нужна прошивка для подключения датчиков температуры ds18

Сб апр 01, 2017 18:13:18

acckyiboxxx писал(а):мне и стало интересно
я уж и не помню формулу вычисления CRC, и вообще лично я пользуюсь давно "библиотечной" функцией для подсчета CRC (в avr-libc avr-gcc входит входит функция)... одно помню: считать CRC надо для всех 9 байтов и если все верно, итог должен быть равен 0...

Re: Всё по DS18(B/S)20.

Сб апр 01, 2017 19:19:30

У меня такой вопрос, а как убедится в актуальности считанной температуры?
Поясню, датчик на паразитном питании, линии заведомо не доверяем.
Алгоритм у меня такой:
1. Ресет датчика
2. Читаю серийник, проверяю crc
3. Даю команду конверт, подтягиваю линию
4. Сплю 0,8сек, снимаю подтяжку
5. Ресет, скип ром, читаю блокнот, проверяю crc
Если на 4ом этапе что то "случайно"(исхожу из максимально плохой ситуации) коротнет цепь, получаю ответ с корректной crc, но там будет 85'C...
В моей ситуации температура 85 считается корректной.
Как детектировать такую ситуацию?

Re: Всё по DS18(B/S)20.

Сб апр 01, 2017 20:44:26

Вопрос из ряда "сам не понял, что спросил".
Как вообще можно узнать, врёт ли датчик и на сколько, относительно реальной температуры ? Правильно, только сравнить его показания с реальной температурой. Иных способов не вижу.
Вы, для начала, определитесь с чем боритесь. Если с "что-то там коротнуло", то и делайте проверку на "коротнуло", а не на показания датчика.

Re: Всё по DS18(B/S)20.

Сб апр 01, 2017 20:54:54

Нет варианта, кроме как 0,8 сек не спать, а опрашивать линию. Лучше, конечно, если есть возможность совместить линию 1-wire с портом ввода-вывода, способным генерировать прерывания, тогда достаточно после истечения времени ожидания посмотреть на флаг запроса этого прерывания - если он установлен, значит "линию что=то коротнуло"

Re: Всё по DS18(B/S)20.

Сб апр 01, 2017 20:59:48

Так вот в том то и дело, показаниям датчика доверяю если crc в норме.
Но если датчик не распознал команду конверт, или на 4ом этапе что то пошло нетак, датчик мне вернет дефолтное значение.
Вопрос, как понять дефолтное это значение или измеренное?

Re: Всё по DS18(B/S)20.

Сб апр 01, 2017 21:01:54

Если датчик не распознал команду конвертирования, то он вернёт не дефолтное значение, а предыдущее после последнего конвертирования.

kinetic писал(а):Вопрос, как понять дефолтное это значение или измеренное?
Никак.
Можно, конечно, извернуться и измерять интенсивность изменения температуры. И если изменилось на много и значение = 85, то тупо отсеить его.

Re: Всё по DS18(B/S)20.

Сб апр 01, 2017 21:18:09

Ну пока я так и сделал: если получили 85, а предыдущий замер был выше 90 или ниже 80 то откидываю, если в течении нескольких замеров ситуация повторяется - выставляю флаг неисправности. Прерывание на пине возможно прикручу. Надеялся может есть флаг какой в ответе датчика...
Но при таком подходе есть шанс выдать ошибку, когда ее нету(температура действительно 85)

Re: Всё по DS18(B/S)20.

Вс апр 02, 2017 03:03:35

При 85 градусах паразитное питание применять не рекомендуется.

Re: Всё по DS18(B/S)20.

Вс апр 02, 2017 04:26:21

Спокойно меряет в полном соответствии с DS.
The use of parasite power is not recommended for temperatures above +100°C since the DS18B20 may not be able to sustain communications due to the higher leakage currents that can exist at these temperatures. For applications in which such temperatures are likely, it is strongly recommended that the DS18B20 be powered by an external power supply.

Re: Всё по DS18(B/S)20.

Вс апр 02, 2017 18:49:44

kinetic писал(а):5. Ресет, скип ром, читаю блокнот, проверяю crc

а зачем в 5 пункте reset? Его не должно быть.
kinetic писал(а):Прерывание на пине возможно прикручу

Не поможет, может быть обрыв у самого датчика, тогда при восстановлении линии вроде как должен сформироваться импульс присутствия, но вы изначально не верите ни линии ни датчику (т.е. импульса может не быть). Лучше сделайте медианный фильтр: самые большые значение и самые маленькие будут отбрасываться, а по остальным идёт усреднение.

Re: Всё по DS18(B/S)20.

Пн апр 03, 2017 00:22:28

dm37 писал(а):а зачем в 5 пункте reset? Его не должно быть.

Ну если верить DS, то всегда необходимо выполнять порядок:
1.Ресет
2.Ром команда
3.Команда действия
И судя по примерам такую последовательность необходимо выполнять всегда.

А по поводу детекта, я тут подумал проще перед конвертом записать значение(например 0xAA) в датчик и при чтении его проверять, если датчик что то сбросило, там тоже будет дефолтное значение.

Re: Всё по DS18(B/S)20.

Пн апр 03, 2017 06:47:09

попутал немного со сбросом, мы используем дополнительно отключение питания датчика и подаём его только на время опроса.
kinetic писал(а):А по поводу детекта, я тут подумал проще перед конвертом записать значение(например 0xAA) в датчик и при чтении его проверять, если датчик что то сбросило, там тоже будет дефолтное значение.

можно конечно попробовать использовать TH/USER BYTE и TL/USER BYTE (без использования команды 0x48 COPY_SCRATCHPAD), но вы же не знаете когда произойдёт сброс датчика в дефолтное состояние. Перед каждой командой проверять эталонное значение?
Я немного не могу понять, что значит что-то сбросило, вы используете паразитное питание и сами же его сбрасываете (команда reset). Если датчик отключается на время большее Treset (вероятно это и есть то что вы хотите поймать), то должен сформироваться импульс присутствия. Т.е. если вы ничего не передаёте и сформировался данный импульс, то датчик сбросился, если вы передаёте и сформировался импульс, то crc будет не верной. В данном случае можно попробовать отловить данную ситуацию с помощью заведения сигнала на вход INT (как уже рекомендовали) и контролировать длительность импульса присутствия, либо время, болшее Treset, но это вроде уже как костыли, завтра вылезет ещё что-то и снова придётся что-то придумывать.
Датчики DS18B20 немного капризные (в отличии от DS18S20), любят затыкаться. Может отказаться от паразитного питания, пересмотреть схему и использовать линию питания (V+). Мы в конечном итоге ушли от простой схемы на транзисторе и доработали схему выходного каскада установив 74HC14 (формирование фронтов) и MAX6314US44D1-T (активная подтяжка для формирования фронтов) LP2985-5.0 (питание датчика со входом отключения). Ну и программный фильтр. Уже работает более 10 лет на плохих линиях связи.

Re: Всё по DS18(B/S)20.

Пн апр 03, 2017 18:36:34

Насколько я понимаю мануал - ресет заставляет датчик прекратить прием/передачу/измерение, но не сбрасывает оперативную память, датчик отвечает сигналом присутствия что готов принимать команду, это просто гарантирует начало приема команды на случай если из-за шумов он уже начал принимать команду.
Я просто добавил перед каждой отправкой команды конверт запись своего значения в TH/USER BYTE и TL/USER BYTE, при считывании температуры мне все равно приходиться читать все 9 байт(иначе не проверить crc), в случае если температура 85 я просто проверяю уже считанные TH/USER BYTE и TL/USER BYTE на предмет того что они равны ранее записанным.
В ближайшее время проверю в боевых условиях работу, если стабильности будет недостаточно переведу на 3ех проводную схему.
Сейчас в офисе на двух 5и метровых кусках провода(максимальная предпологаемая длина) время от времени считывает с 3-5 попытки, мне достаточно обновления раз в 10сек.
Ответить