Артемон Опубликовано 1 января, 2016 Поделиться Опубликовано 1 января, 2016 (изменено) Всем привет. Просьба посодействовать в исправлении кода для термометра. Так как сам я в этом новичек, то код собирал из трех чужих проектов. Реализация такова, подключение термопары через микруху Max6675 к Atmega и вывод данных на LCD экран. В архиве прилагаю проект Atme Studio 7 и принт скрин из Протеуса. Ошибка заключается в неправильных показаниях температуры Test1.rar Вот код, чтоб не скачивать проект. #define F_CPU 1000000UL #include <util/delay.h> #include <avr/io.h> #include "max6675.h" #include "LCD.h" uint16_t gettemp(void); //Funktionsdeklarationen void initavr(void); //gettemp () returns absolute Temperature in Temp * 4 °C - in 1/4°-steps // uint16_t gettemp(void){ //Temperatur holen. uint8_t bit = 0, bitnr = 12; //Variablen uint8_t foo1 = 0; uint16_t Rohdata = 0; CS_Port &= ~(1 << CS); //Chip select anlegen for(foo1 = 0 ; foo1 < 16 ; foo1++){ //16 Bits einlesen bit = 15 - foo1; //Die Aktuelle Bitnr berechnen. SCK_Port |= (1 << SCK); //SCK hi if((bit <= 14) && (bit >= 3)){ //Einfach mal die 12 relevanten von den 16 Bits ausfiltern if((SO_Pin & (1 << SO))){ //WENN SO 1 ist, dann... bitnr--; //zдhlen wir runter... Rohdata |= (1 << bitnr); // und schieben eine 1 an bit x }else{ //WENN dem NICHT so ist, dann... bitnr--; //zдhlen wir runter... Rohdata &= ~(1 << bitnr); //und schieben eine 0 an bit x } }else{ //weis au nimmer, was das soll. bitnr = 12; } SCK_Port &= ~(1 << SCK); //SCK LO } CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. return Rohdata; //Das ist doch mal was ;D } // getTC() returns 0 if Thermocouple is not connected, 255 if thermocuple is connected // (to enable this feature T- must be connected to GND) uint8_t getTC(void){ //Temperatur holen. //Variablen uint8_t TC = 0; uint8_t foo1 = 0; CS_Port &= ~(1 << CS); //Chip select anlegen for(foo1 = 0 ; foo1 < 16 ; foo1++){ //16 Bits einlesen //Die Aktuelle Bitnr berechnen. SCK_Port |= (1 << SCK); //SCK hi if(foo1 == 2){ //das 3. bit ist fьr uns relevant. if((SO_Pin & (1 << SO))){ //WENN SO 1 ist, dann... TC = 0; }else{ //WENN dem NICHT so ist, dann... TC = 255; } } SCK_Port &= ~(1 << SCK); //SCK LO } CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. return TC; //Das ist doch mal was ;D } //Initiates the MAX6675 and IO-pins void init_6675(void){ //AVR initialisieren SO_DDR &= ~(1 << SO); CS_DDR |= (1 << CS); SCK_DDR |= (1 << SCK); //IOs setzen SO_Port |= (1<<SO); //Pullups an. (Wichtig fьr MAX6675, der kann nicht anders, hab ich festgestellt... CS_Port |= (1 << CS); //CS HI //Alles auf Standardkonfig. SCK_Port &= ~(1 << SCK); //SCK LO } int main(void) { init_port();// инициализируем порт ЖКИ lcd_init();// инициализируем ЖКИ init_6675(); while (1) { char buffer[8]; int temp; temp = gettemp(); temp /=4; lcd_gotoxy(0,0);//перемещаем курсор в верхний левый угол sprintf(buffer, "t=%i\xdf\C ", temp); // так как тут не плавающая запятая то числа с запятой записываются так %i.%i, код градуса записывается так \xdf lcd_putstring(buffer); } } вставляете код пользуйтесь тегами [CОDE][/CОDE] редактора сообщений, кнопка <> Изменено 2 января, 2016 пользователем Артемон 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Yurkin2015 Опубликовано 1 января, 2016 Поделиться Опубликовано 1 января, 2016 Надо temp разделить на 4, и будет правильная температура 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
20% скидка на весь каталог электронных компонентов в ТМ Электроникс!Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!Перейти на страницу акции Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 Надо temp разделить на 4, и будет правильная температура добавил строку temp /= 4; , теперь при нуле градусов на датчике, на экране показывает 24 градуса, но уже при изменении температуры на датчике на 1 градус она меняется соответственно на 1 градус на экране Не знаю правильно это или нет но я добавил еще такую строку temp -=24; теперь отсчет температуры от нуля соответствует норме 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>> Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 Осталось написать функцию для корректировки погрешности. Вот что теперь выдает термометр: (слева температура на датчике, справа температура на экране) 100 = 100 200 = 198 300 = 297 400 = 399 500 = 503 600 = 606 700 = 709 800 = 810 900 = 908 В принципе мне этой точности достаточно, но если у кого есть идеи буду рад 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
o_l_e_g Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 Проверь в свойствах мах6675 температуру холодного спая. PS ЕМНИП, она идет как "окружающая температура". 1 Errare humanum est. Коли людЯм позволено, что же о нас то говорить! Ссылка на комментарий Поделиться на другие сайты Поделиться
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 Если я правильно понимаю из даташита, то температура холодного спая (Cold junction) TA = -20°C to +85°C MAX6675 datasheet.pdf 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
o_l_e_g Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 Ну да. В симуляторе, ставится вручную. А температура на термопаре, высчитывается с учетом коррекции ХС. 0 Errare humanum est. Коли людЯм позволено, что же о нас то говорить! Ссылка на комментарий Поделиться на другие сайты Поделиться
Yurkin2015 Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 я добавил еще такую строку temp -=24; теперь отсчет температуры от нуля соответствует норме Вычитать 24 градуса нужно, видимо, только для симулятора. Для реального устройства в железе вычитать не нужно, т.к. микросхема MAX6675 сама будет учитывать температуру холодного спая и выдавать уже готовый правильный результат. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
o_l_e_g Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 Она и в симуляторе будет в корректироваться, только внести в свойства элементов и всё. 1 Errare humanum est. Коли людЯм позволено, что же о нас то говорить! Ссылка на комментарий Поделиться на другие сайты Поделиться
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 я добавил еще такую строку temp -=24; теперь отсчет температуры от нуля соответствует норме Вычитать 24 градуса нужно, видимо, только для симулятора. Для реального устройства в железе вычитать не нужно, т.к. микросхема MAX6675 сама будет учитывать температуру холодного спая и выдавать уже готовый правильный результат. Судя по всему так и есть, так как в протеусе на MAX6675 стояла температура холодного спая +25гр, переписал на 0гр и она соответственно изменилась, так что строка temp -=24; я убираю 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Yurkin2015 Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 Ну, замечательно. Интересно, а ошибки измерения тоже заложены в симуляторе? И именно их Артемон собрался компенсировать? 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
o_l_e_g Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 Это вряд ли. Когда то, разбирался с этой МС. На низком уровне в протезе, она выдает всё точно. Видимо, ошибки в программе обработки. 1 Errare humanum est. Коли людЯм позволено, что же о нас то говорить! Ссылка на комментарий Поделиться на другие сайты Поделиться
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 После того, как выставил в протеусе температуру холодного спая на 0 и убрал строку temp -=24; 0гр определяет как 0 1 градус определяет как 0 2 градуса как 1 и дальше 100=99 200=197 300=296 400=398 и т.д. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
o_l_e_g Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 Сними осциллограмму с интерфейса МАХ, и проанализируй. 1 Errare humanum est. Коли людЯм позволено, что же о нас то говорить! Ссылка на комментарий Поделиться на другие сайты Поделиться
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 Мне кажется что ошибка в блоке uint16_t gettemp(void), попробую поискать чтото подобное Я в этом всем новичек так что не пинайте сильно, для меня эта осцилограмма как 100 баксов для бабуина 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
o_l_e_g Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 Интересуют "красный" канал- данные, и "синий"- тактирование. Раздвинь по времени один кадр, и для каждого клока запиши значение передаваемых данных на бумажке. Потом посмотри, как описывается передача в даташите. Станет ясно, что передается. 1 Errare humanum est. Коли людЯм позволено, что же о нас то говорить! Ссылка на комментарий Поделиться на другие сайты Поделиться
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 разворачивать вроде научился, щас буду разбираться дальше 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 (изменено) Нашел в поисковике альтернативный вариант кода, дает точно такой же результат как и в первом коде #define F_CPU 1000000UL #include <inttypes.h> #include <avr/io.h> #include <stdlib.h> #include <util/delay.h> //#include <avr/pgmspace.h> #include "MAX6675.h" #include "LCD.h" /************************************************************************* Read the temperature Value Input: none Returns: 0xFFFF: ERROR else: Temperatur Value * 4 [°C] *************************************************************************/ uint16_t MAX6675ReadTemp(void) { uint16_t tempRead; uint8_t valRead; // pull SS Line low SPI_PORT &= ~(1<<SS_BIT); // start SPI data transfer SPDR = 0x00; // wait for transmision complete while(!(SPSR & (1<<SPIF))) ; // do nothing // copy hi byte valRead = SPDR; // start SPI data transfer SPDR = 0x00; // shift hi-byte tempRead = valRead << 5; // wait for transmision complete while(!(SPSR & (1<<SPIF))) ; // do nothing // copy hi byte valRead = SPDR; valRead &= 0b11111000; valRead >>= 3; tempRead |= valRead; // pull SS Line hi SPI_PORT |= (1<<SS_BIT); return tempRead; } /************************************************************************* * Initialize the SPI Port to communicate with MAX6675 * Input: none * Returns: none ************************************************************************/ void MAX6675Init(void) { //volatile char IOReg; // set /SS, MOSI, SCK as output SPI_DDR |= (1<<SS_BIT)|(1<<MOSI_BIT)|(1<<SCK_BIT); // enable SPI in Master Mode with SCK = CK/128 SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<SPR0)|(1<<SPR1); //IOReg = SPSR; // clear SPIF bit in SPSR //IOReg = SPDR; } int main(void) { init_port();// инициализируем порт ЖКИ lcd_init();// инициализируем ЖКИ MAX6675Init(); while (1) { char buffer[8]; int temp; temp = MAX6675ReadTemp(); temp /= 4; lcd_gotoxy(0,0);//перемещаем курсор в верхний левый угол sprintf(buffer, "t=%i\xdf\C ", temp); // так как тут не плавающая запятая то числа с запятой записываются так %i.%i, код градуса записывается так \xdf lcd_putstring(buffer); } } Изменено 2 января, 2016 пользователем Артемон 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Артемон Опубликовано 2 января, 2016 Автор Поделиться Опубликовано 2 января, 2016 В общем выставил температуру холодного спая на MAX6675 в протеусе на +1 градус, теперь отсчет начинается правильно Тоесть 0гр на датчике соответствует 0гр на экране Без погрешности все идет до 163гр на датчике Ну и далее такие показатели: 200 = 198 300 = 297 400 = 399 500 = 503 600 = 606 700 = 709 800 = 810 900 = 908 Осцилограмма немного изменилась, но я по прежнему в ней не разобрался 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
o_l_e_g Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 В даташите рисунке 1а и b и есть эти осциллограммы. Вычлени 12 бит данных, цена бита 0.25 градусов, перемножь получится температура. . 1 Errare humanum est. Коли людЯм позволено, что же о нас то говорить! Ссылка на комментарий Поделиться на другие сайты Поделиться
Yurkin2015 Опубликовано 2 января, 2016 Поделиться Опубликовано 2 января, 2016 (изменено) Дело тут не в SPI, мне кажется. Вот пример из Гугла для симуляции термопары. Надо тоже вывод CJ как-то задейстовать: заземлить, например, для 0 градусов окружающего. Изменено 2 января, 2016 пользователем Yurkin2015 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Артемон Опубликовано 3 января, 2016 Автор Поделиться Опубликовано 3 января, 2016 Дело тут не в SPI, мне кажется. Вот пример из Гугла для симуляции термопары. Надо тоже вывод CJ как-то задейстовать: заземлить, например, для 0 градусов окружающего. Пробовал повторять, индикатор показывает 0 Я тоже думаю что дело не в SPI так как 2 разные прошивки дают один результат. Думаю что в реальных условиях значения будут нормальные, так что будем считать тему закрытой, всем спасибо. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
DrunyaRuma Опубликовано 27 мая, 2016 Поделиться Опубликовано 27 мая, 2016 Привет, я преобразую в температуру так: float cl_MAX6675::ConvertDataToFloat(unsigned short tData) { float tRez; unsigned short a, b; tData = tData >> 3; b = tData & 0x0003; tRez = tData >> 2; for(a = 0; a < b; a++) tRez = tRez + 0.25; return tRez; } передаваемый параметр в функцию это данные считанные с микросхемы. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Никита Опубликовано 15 июня, 2016 Поделиться Опубликовано 15 июня, 2016 Можно устранить погрешность,найдя средний результат из выборки и устранить дробную часть,тогда разброс в температуре будет намного меньше. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.