Помогите решить проблему с DS18b20

Модератор: boogyman

Ответить
Аватара пользователя
Skipper
Новичок
Сообщения: 1
Зарегистрирован: 28 фев 2019, 08:58

Помогите решить проблему с DS18b20

#1

Сообщение Skipper » 28 фев 2019, 09:08

Здравствуйте. Сам я далек от программирования, но возникшая проблема вынуждает обратиться к вам за помощью.
Имеется: линия с 8 DS18B20 - cхемка на двух транзисторах(внизу) - адаптер RS232-USB "Z-Tek" - компьютер - программа TempKeeper. Система отлично работала несколько дней и вдруг:
1 - На одном датчике стала плавать(произвольно меняться в процессе измерения) битность с 9 до 12. В свойствах датчика битность - 12
2 - На другом датчике стала плавать(произвольно меняться в процессе измерения) битность с 9 до 11. В свойствах битность - 11
3 - На остальных битность 9, в свойствах - пробел. Программой задана на все датч битность 12
Первым делом отключил линию, подключил новый DS прямо на плату, результ - см выше п.1 . Пробовал поменять комп и ставил другие программы Т-мониторинга - все то же самое. Еще пробовал время изм 750мс менять.
Для меня важна не столько точность, сколь высокое разрешение.
Очень надеюсь на вашу помощь.
aaa.gif
aaa.gif (7.51 КБ) 4533 просмотра

Аватара пользователя
nike
Новичок
Сообщения: 8
Зарегистрирован: 04 май 2020, 14:34

Re: Помогите решить проблему с DS18b20

#2

Сообщение nike » 06 май 2020, 23:50

Здравствуйте. Запустил в протеусе термометр по этой статье https://radioparty.ru/programming/avr/c ... n2-ds18b20 На Atmega 8, всё работает. Хотел переделать под Atmega328p, заменил в настройках таймера регистры TIMSK и TCCR2 на TIMSK2 и TCCR2B, всё остральное не трогал. В итоге экран показывает одни прочерки (. Подскажите пожалуйста, может я забыл ещё что-то изменить ? Вот на всякий случай код

Код: Выделить всё

// Подключение цифровых датчиков температуры DS18B20 к AVR
#define F_CPU 8000000UL // Устанавливаем рабочую частоту контроллера
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

// Массив значениий для семисегментного индикатора
char SEGMENTE[] =
{
	0x3F, // 0
	0x06, // 1
	0x5B, // 2
	0x4F, // 3
	0x66, // 4
	0x6D, // 5
	0x7D, // 6
	0x07, // 7
	0x7F, // 8
	0x6F, // 9
	0x40, // "минус"
	0x00  // "пусто"
};
unsigned char segcounter = 0;
volatile unsigned char display_1, display_2, display_3, display_4;

// Прерывание по переполнению T2, динамическая индикация
ISR (TIMER2_OVF_vect)
{
	PORTD = 0xFF;
	PORTB = (1 << segcounter);
	
	switch (segcounter)
	{
		case 0:
		PORTD = ~(SEGMENTE[display_1]);
		break;
		case 1:
		PORTD = ~(SEGMENTE[display_2]);
		break;
		case 2:
		PORTD = ~((SEGMENTE[display_3])|0x80); // добавляем точку
		break;
		case 3:
		PORTD = ~(SEGMENTE[display_4]);
		break;
	}
	if ((segcounter++) > 2) segcounter = 0;
}

unsigned char Temp_H, Temp_L, OK_Flag, temp_flag;

// Инициализация DS18B20
unsigned char DS18B20_init(void)
{
	DDRC |= (1 << PC0); // PC0 - выход
	PORTC &= ~(1 << PC0); // Устанавливаем низкий уровень
	_delay_us(490);
	DDRC &= ~(1 << PC0); // PC0 - вход
	_delay_us(68);
	OK_Flag = (PINC & (1 << PC0)); // Ловим импульс присутствия датчика
	// если OK_Flag = 0 датчик подключен, OK_Flag = 1 датчик не подключен
	_delay_us(422);
	return OK_Flag;
}

// Функция чтения байта из DS18B20
unsigned char read_18b20(void)
{
	unsigned char i, data = 0;
	for(i = 0; i < 8; i++)
	{
		DDRC |= (1 << PC0); // PC0 - выход
		_delay_us(2);
		DDRC &= ~(1 << PC0); // PC0 - вход
		_delay_us(4);
		data = data >> 1; // Следующий бит
		if(PINC & (1 << PC0)) data |= 0x80;
		_delay_us(62);
	}
	return data;
}

// Функция записи байта в DS18B20
void write_18b20(unsigned char data)
{
	unsigned char i;
	for(i = 0; i < 8; i++)
	{
		DDRC |= (1 << PC0); // PC0 - выход
		_delay_us(2);
		if(data & 0x01) DDRC &= ~(1 << PC0);
		else DDRC |= (1 << PC0);
		data = data >> 1; // Следующий бит
		_delay_us(62);
		DDRC &= ~(1 << PC0); // PC0 - вход
		_delay_us(2);
	}
}

// Главная функция
int main(void)
{
	// Настройка портов ввода/вывода
	DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3); // Разряды
	PORTB = 0x00;
	DDRD = 0xFF; // Сегменты
	PORTD = 0x00;
	// Настройка Т2
	TIMSK2 |= (1 << TOIE2); // Разрешение прерывания по Т2
	TCCR2B |= (1 << CS21);  // Предделитель на 8
	
	unsigned int buffer;
	unsigned int temp_int_1,temp_int_2,temp_int_3; // Переменные для целого значения температуры
	unsigned int temp_point; // Переменная для дробного значения температуры

	sei(); // Глобально разрешаем прерывания
	
	while(1)
	{
		// Если датчик не ответил выводим "минус" во всех разрядах
		if(OK_Flag) display_1 = display_2 = display_3 = display_4 = 10;

		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 temp;
			temp_flag = 0;      // Флаг знака равен 0(минус)
			temp = (Temp_H << 8)|Temp_L;
			temp = -temp; // Переводим дополнительный код в прямой
			Temp_L = temp;
			Temp_H = temp >> 8;
		}

		// Вычисляем целое значение температуры
		buffer = ((Temp_H << 4) & 0x70)|(Temp_L >> 4);
		temp_int_1 = buffer % 1000 / 100;
		temp_int_2 = buffer % 100 / 10;
		temp_int_3 = buffer % 10;

		// Вычисляем дробное значение температуры
		if(temp_flag == 0) buffer = (Temp_L & 0x0F) + 1;
		else buffer = (Temp_L & 0x0F);
		temp_point = buffer * 625 / 1000; // Точность темпер.преобразования(0.0625)

		// Если флаг знака температуры равен 0, в первом разряде ставим минус
		if(temp_flag == 0) temp_int_1 = 10; // "минус"
		// Если первая цифра значения температуры меньше 1, то гасим 1-й разряд индикатора
		if(temp_int_1 < 1) temp_int_1 = 11; // "пусто"
		// Если первая цифра погашена и вторая цифра значения температуры меньше 1, то гасим 2-й разряд индикатора
		if(temp_int_1 == 11 && temp_int_2 < 1) temp_int_2 = 11; // "пусто"
		// Если вторая цифра значения температуры меньше 1 и знак равен "минус", то гасим 2-й разряд индикатора
		if(temp_int_2 < 1 && temp_flag == 0) temp_int_2 = 11; // "пусто"

		// Выводим значения на дисплей
		display_1 = temp_int_1;
		display_2 = temp_int_2;
		display_3 = temp_int_3;
		display_4 = temp_point;

	}
}

Аватара пользователя
AntonChip
Администратор
Сообщения: 255
Зарегистрирован: 24 дек 2011, 22:11
Откуда: Киров
Контактная информация:

Re: Помогите решить проблему с DS18b20

#3

Сообщение AntonChip » 07 май 2020, 10:15

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

Аватара пользователя
microsystems
Любитель
Сообщения: 12
Зарегистрирован: 11 дек 2019, 19:40

Re: Помогите решить проблему с DS18b20

#4

Сообщение microsystems » 07 май 2020, 10:20

прочерки - значит датчик не читается, так вроде бы?

Аватара пользователя
nike
Новичок
Сообщения: 8
Зарегистрирован: 04 май 2020, 14:34

Re: Помогите решить проблему с DS18b20

#5

Сообщение nike » 07 май 2020, 11:37

А atmel studio и протеусе стоит 8 Мгц
CLKDIV8
А где его проверить ?

Аватара пользователя
nike
Новичок
Сообщения: 8
Зарегистрирован: 04 май 2020, 14:34

Re: Помогите решить проблему с DS18b20

#6

Сообщение nike » 07 май 2020, 11:46

Нашёл, в протеусе поставил CLKDIV8 в (1) Unprogrammed, было (0) Programmed и всё заработало. А как в железе нормально будет работать ?

Аватара пользователя
AntonChip
Администратор
Сообщения: 255
Зарегистрирован: 24 дек 2011, 22:11
Откуда: Киров
Контактная информация:

Re: Помогите решить проблему с DS18b20

#7

Сообщение AntonChip » 07 май 2020, 12:15

В железе работает, проверено

Аватара пользователя
nike
Новичок
Сообщения: 8
Зарегистрирован: 04 май 2020, 14:34

Re: Помогите решить проблему с DS18b20

#8

Сообщение nike » 07 май 2020, 13:01

AntonChip писал(а):
07 май 2020, 12:15
В железе работает, проверено
У меня не получилось( Правда у меня другой дисплей (SSD1306). Пробую выводить на него переменные temp_int_1,temp_int_2,temp_int_3.
Вместо них экран показывает :;01 При нагревании датчика нечего не меняется. Может при прошивке в avrdude попробывать убрать галочку с фьюза CKDIV8 ?

Аватара пользователя
nike
Новичок
Сообщения: 8
Зарегистрирован: 04 май 2020, 14:34

Re: Помогите решить проблему с DS18b20

#9

Сообщение nike » 07 май 2020, 13:29

Ура заработало. Пришлось убрать галочку CKDIV8 в avrdude. Спасибо за помощь.

Ответить