Научи ме

Програмиране => C/C++ => Темата е започната от: jazzman в 25 Октомври 2016, 03:53:43

Титла: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 25 Октомври 2016, 03:53:43
Опитвам се да включа time/date функциите към файла си, но плющът грешки. Според документацията библиотеката е включена към AVR - http://www.nongnu.org/avr-libc/user-manual/group__avr__time.html. Да не би да нямам инсталирана avr_libc  :)

Код: C
  1. #include <stdio.h>
  2. #include <avr/io.h>
  3. #include <util/delay.h>
  4. #include <time.h>
  5.  
  6. void wait ( int sec ) {
  7.                 clock_t end_wait;
  8.                 end_wait = clock () + sec * CLK_TCK ;
  9.  
  10.                 while (clock() < end_wait) {}
  11. }
  12.  
  13. int main(void) {
  14.  
  15. DDRB |= _BV(DDB5);
  16. while(1) {
  17. PORTB |= _BV(PORTB5);
  18. wait (5);
  19.  
  20. PORTB &= ~_BV(PORTB5);
  21. wait (5);
  22.   }
  23. }
  24.  

Цитат
dimt@dimt-Satellite-L670 ~ $ avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o led.c
led.c:4:18: fatal error: time.h: No such file or directory
 #include <time.h>

Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 25 Октомври 2016, 13:36:22
Иглежда като да го нямаш тоз хедър. Според changelog-а на avr-libc (http://www.nongnu.org/avr-libc/NEWS.txt) time.h е добавен във версия 1.8.1
Пробвай да принтнеш версията, която използваш
Код: C
  1. printf("libc version: %s\n", __AVR_LIBC_VERSION_STRING__);
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 25 Октомври 2016, 14:20:11
С 1.8.0 съм. Ще се пробвам да инсталирам / компилирам 2.0.0 
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 25 Октомври 2016, 14:59:14
Ако си любознателен по-добре ще е да си имплементираш собствен ташовник. :)
1. нягласяш някой от таймерите да ти генерира интеръпти примерно на всяка милисекунда (хем таймери ще научиш, хем интеръпти)
2. около тази милисекунда си имплементираш твоите epoch time фунцкии - изминали милисекунди от  01.01.1970 (малко гимнастика с дати, високосни години  и тнт.)

Едит:

1. Като гледам документацията на time.h
Цитат на: http://www.nongnu.org
Section 7.23.2.1 clock() The type clock_t, the macro CLOCKS_PER_SEC, and the function clock() are not implemented. We consider these items belong to operating system code, or to application code when no operating system is present.

та фунцкията и структурата, които си използвал изобщо не са имплементирани.

2. това което си опитал да имплементираш в кода си е функция наиричаща се delay_us/sleep_us или delay_ms/sleep_ms и по принцип изглежда нещо като това
Код: C
  1. void sleep_ms(int millis) {
  2.    uint32_t end = millisec + millis; // където millisec e глобалната променлива, която инкрементираш на всеки интеръпт, който си натроил с тамера
  3.    while (millisec < end) { ; }
  4. }


И съответно като искаш да подремнеш за 5 секунди викаш
Код: C
  1. sleep_ms(5*1000);
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 25 Октомври 2016, 18:52:49
Мислих за нещо подобно. Значи да споделя за кво ми е па ти шъ ма насочиш :)
Искам всеки 2-ри петък от месеца да се стартира  фърниса и джакузито на котиджа ми, че като пристигна след 2 - 3 часа всичко да е на 6. Не че нещо ми пречи да се логна отдалечено от Торонто и да го стартирам мануално, ама .......тръпка ми е кода да го направи вместо мен ;)   
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 25 Октомври 2016, 20:46:51
Искаш един път в месеца да подскача твоето приложение, така ли?
Какъв смяташ да е power source-a ти? Батерии?
Вариантите които виждам са 2.
 - имплементираш си unix time  с календар и тнт и си нагласяш дата и час когато нещо да се случва.
 - пишеш код който има нещо като аларма, която задействаш преди да потеглиш обратно за Торонто. Примерно потегляш в неделя в 14 часа и си смяташ, че следващият път ще е след 26 дена или 2246400000 милисекунди и си нагласяш "алармата" за след това време да включи квото има да включва.

Но да ти кажа за такива големи периоди ми се струва голям овъркил да работи микроконтролера цял месец за да генерира един интеръпт  ;D А и да ти кажа не знам как сте у Канада-та със застраховките, но мисля, че не биха поели щетите, ако им кажеш, че си си билднал сам детонатора  ;D

Кварца който ползваш има доста ограничена точност, което означава, че часовника, който имплементираш ще дрифтва постоянно и няма да е никак точен. Чел съм за дрифт от по 5-10 сек/ден. С колко ще се отклонява от реалното време и дали напред, или назад зависи от самият кварц, от околната температура и тнт. Най-добре е да се комбинира с един GNSS, с който редовно да сверяваш часовника.

Другото което е, ако смяташ да си на бактерии ще трябва много да оптимизираш кода. Да изключиш всичкото периферия що не се ползва, да разредиш интеръпт-интервалите и тнт. Иначе батериите няма да те издържат и 2 седмици.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 25 Октомври 2016, 22:18:13
E...то ся ми дойде още нещо на ума говорейки за тва ;)
Мога да ползвам cronjob който да флашва C кода в джаджата всеки втори петък от месеца,  а в неделята преди да тръгна за Торонто да си слага старият и тва е вариант мисля.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 25 Октомври 2016, 22:26:38
Цитат
Искаш един път в месеца да подскача твоето приложение, така ли?
Какъв смяташ да е power source-a ти? Батерии?

С комп съм. Какво имаш предвид под  power-source? power-source на кое?   
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 26 Октомври 2016, 00:19:47
Да флашваш микроконтролера всеки път няма смисъл. По-скоро да го ресетваш примерно, или да му пращаш команди през uart.

За power source имах предвид как смяташ да захранваш uC-то. На батерии ли ще е, ще виси на USB-порт на компа, или с външно захранване някакво.

Явно ще виси на компа, а аз мислех, че правиш stand-alone приложение.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 26 Октомври 2016, 04:02:28
Цитат
Да флашваш микроконтролера всеки път няма смисъл. По-скоро да го ресетваш примерно, или да му пращаш команди през uart.
И на мен ми се вижда малко брутално на всеки две седмици да го флашвам :) Къде мога да прочета повече, тва за пращането на команди през UART?

uC-то се захранва от USB кабела към PC-то зад което стои мощен UPS.

Между-другото Ардуино Uno има и джак за DC power adapter. Четох някъде, че има волтидж регулейтор към 5v. Дали ще мога да ги ползвам паралелно и двата. USB-то към PC-то за Data а power adapter-a като el. source?   
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 26 Октомври 2016, 20:48:20
Ти UART вече ползваш за printf. Сега искаш обаче не само да пишеш в този UART порт, но и да четеш от него. Демек искаш да се свържеш през някоя терминал програма с микроконтролера и да пращаш някакви стрингове/команди.

Тъй като ползваш printf, приемам че знаеш как се свързваш през serial с микриконтролера. Във функцията void USART0Init(void); си включил изпращащ и получаващ интеръпт.
Значи единственото което трябва да допълниш е interrupt handler-a за получаващият интеръпт, където събираш получените байтовете.

НЕщо такова:

Код: C
  1. #define RX_BUFF_SIZE 50
  2.  
  3. volatile unsigned char lineBuffer[RX_BUFF_SIZE] = {0};
  4. volatile uint8_t idx = 0;
  5.  
  6. ISR(USART_RXC_vect)
  7. {
  8.   unsigned char c;
  9.   c = UDR;                              // четем от регистъра съдържащ полуленият байт
  10.   lineBuffer[idx] = c;                  // пишем го в буфера
  11.   idx++;                                // минаваме на следваща позиция в буфера за следващият знак, който ще получим
  12.   if(c == '\n') {                       // ако видим line feed , значи сме прочели цял ред -> цяла команда
  13.      lineBuffer[idx] = '\0';            // терминираме стринга с една 0
  14.      interpretCmd(lineBuffer);          // интерпретираме командата
  15.      idx = 0;                           // зануляваме индекса, за да пишем от началото на буфера при следващ получен байт
  16.   }
  17. }


Кода не е тестван и няма как да го тествам, защото нямам никакви AVR-и при мене в момента.
В кода естествено трябва да правиш и проверка дали не си стигнал края на буфера RX_BUFF_SIZE и да реагираш съответно.

Колкото до паралелно ползване на адаптер с USB не би трябвало да има никакъв проблем.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 28 Октомври 2016, 01:12:12
И аз няма как да го тествам в момента, но ще пиша при първи удобен за мен случай :)
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 28 Октомври 2016, 19:26:53
Е ако не друго то поне името на регистъра съм сбъркал. :)
При atmega328p видях, че е UDR0, а не UDR.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 29 Октомври 2016, 02:02:05
Е ако не друго то поне името на регистъра съм сбъркал. :)
При atmega328p видях, че е UDR0, а не UDR.
E.....и ти не си безгрешен  ;D
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 29 Октомври 2016, 17:19:04
E.....и ти не си безгрешен  ;D
Аз не си спомням кога за последно съм написал два реда код без грешка.  :D
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 10 Ноември 2016, 03:48:09
Добре стигнах до тук:

Код: C
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <avr/io.h>
  4. #include <util/delay.h>
  5.  
  6. #define NUM_READINGS 10
  7. #define ADC_CHANNEL 0
  8. #define USART_BAUDRATE 9600
  9. #define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
  10. #define RX_BUFF_SIZE 50
  11.  
  12. void USART0Init(void)
  13.  
  14. {
  15.  
  16. // Set baud rate
  17.  
  18. UBRR0H = (uint8_t)(UBRR_VALUE>>8);
  19.  
  20. UBRR0L = (uint8_t)UBRR_VALUE;
  21.  
  22. // Set frame format to 8 data bits, no parity, 1 stop bit
  23.  
  24. UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
  25.  
  26. //enable transmission and reception
  27.  
  28. UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
  29.  
  30. }
  31.  
  32. void USART0SendByte(char u8Data, FILE *stream) {
  33.  
  34.     if(u8Data == '\n')
  35.     {
  36.         USART0SendByte('\r', stream);
  37.     }
  38.     //wait while previous byte is completed
  39.     while(!(UCSR0A&(1<<UDRE0))){};
  40.     // Transmit data
  41.     UDR0 = u8Data;
  42. }
  43.  
  44. uint8_t USART0ReceiveByte() {
  45.  
  46. // Wait for byte to be received
  47.  
  48. while(!(UCSR0A&(1<<RXC0))){};
  49.  
  50. // Return received data
  51.  
  52. return UDR0;
  53.  
  54. }
  55.  
  56. void InitADC(void) {
  57.  
  58.         // Select Vref=AVcc
  59.         ADMUX |= (1<<REFS0);
  60.         //set prescaller to 128 and enable ADC
  61.         ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADEN);    
  62. }
  63.      
  64. uint16_t ReadADC(uint8_t ADCchannel) {
  65.        
  66.         ADMUX = (ADMUX & 0xF0) | (ADCchannel & 0x0F);
  67.    
  68.         ADCSRA |= (1<<ADSC);
  69.      
  70.         while( ADCSRA & (1<<ADSC) );
  71.        
  72.         return ADC;
  73. }
  74.  
  75. float ReadAndReturnAVG(uint8_t channel,  uint16_t *values, int sizeOfValues) {
  76.  
  77.        int i = 0;
  78.        
  79.        int  total = 0;
  80.  
  81.        float average = 0.0f;
  82.  
  83.         for (i = 0; i < sizeOfValues; i++) {
  84.  
  85.             values[i] = ReadADC(channel); // тука може да ползваме функцията ReadADC,защото
  86.                                            
  87.             total = total + values[i];    // няма нужда от екстра loop за сбора
  88.             _delay_ms(300);
  89.         }
  90.  
  91.         average = (float)total / (float)sizeOfValues;
  92.  
  93.         return average;
  94.        
  95. }
  96.  
  97. //set stream pointer
  98. FILE usart0_str = FDEV_SETUP_STREAM(USART0SendByte, NULL, _FDEV_SETUP_WRITE);
  99.  
  100. int main (void)
  101. {
  102.  
  103. DDRB = 0xff; // Set Port B as Output
  104.  
  105. PORTB = 0x00;
  106.  
  107. //initialize ADC
  108. InitADC();
  109.  
  110. float sensorData = 0.0f;
  111.  
  112. int reading;
  113.  
  114. uint16_t values[NUM_READINGS] = {0};
  115.  
  116. //Initialize USART0
  117.  
  118. USART0Init();
  119.  
  120. while(1) {
  121.  
  122. // Receive data
  123. //u8TempData = USART0ReceiveByte();
  124.  
  125. stdout = &usart0_str;
  126.  
  127. sensorData = ReadAndReturnAVG(ADC_CHANNEL, values, NUM_READINGS);
  128.  
  129. reading = ISR();
  130.  
  131. printf("mV: %d reading: %d\n", (int)(round(sensorData)),reading);
  132.  
  133. //Increment received data
  134.  
  135. //u8TempData++;
  136.  
  137. //Send back to terminal
  138. //USART0SendByte(u8TempData);
  139.   }
  140. }
  141.  
  142. volatile unsigned char lineBuffer[RX_BUFF_SIZE] = {0};
  143.  
  144. volatile uint8_t idx = 0;
  145.  
  146. ISR(USART_RXC_vect)
  147. {
  148.   unsigned char c;
  149.   c = UDR0;                              // четем от регистъра съдържащ полученият байт
  150.   lineBuffer[idx] = c;                  // пишем го в буфера
  151.   idx++;
  152.    if(c == '\n') {                       // ако видим line feed , значи сме прочели цял ред -> цяла команда
  153.      lineBuffer[idx] = '\0';            // терминираме стринга с една 0
  154.     // interpretCmd(lineBuffer);          // интерпретираме командата
  155.      idx = 0;                           // зануляваме индекса, за да пишем от началото на буфера при следващ получен байт
  156.   }
  157. return (int) lineBuffer;
  158. }
  159.  

Резултата е този:

Цитат
mV: 150 reading: 291
mV: 150 reading: 291
mV: 150 reading: 291
mV: 150 reading: 291
mV: 150 reading: 291
mV: 150 reading: 291
mV: 150 reading: 291
mV: 150 reading: 291
mV: 150 reading: 291
mV: 150 reading: 291


Ако въведа някакъв произволен номер в терминала, да речем - echo 87 > /dev/ttyACM0

Стойноста на reading-a не се променя.

Идеята тук е да съпоставя стойноста въведена в терминала с тази от сензора.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 10 Ноември 2016, 03:58:13
Примерно с този код съм способен да вкарвам и чета командите писани в терминала, но не ми идва на акъла как да взема и да съпоставя стойностите излизащи от сензора:


Код: C
  1. #include <avr/io.h>
  2. #define USART_BAUDRATE 9600
  3. #define UBRR_VALUE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
  4. void USART0Init(void)
  5. {
  6. // Set baud rate
  7. UBRR0H = (uint8_t)(UBRR_VALUE>>8);
  8. UBRR0L = (uint8_t)UBRR_VALUE;
  9. // Set frame format to 8 data bits, no parity, 1 stop bit
  10. UCSR0C |= (1<<UCSZ01)|(1<<UCSZ00);
  11. //enable transmission and reception
  12. UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
  13. }
  14. void USART0SendByte(uint8_t u8Data)
  15. {
  16. //wait while previous byte is completed
  17. while(!(UCSR0A&(1<<UDRE0))){};
  18. // Transmit data
  19. UDR0 = u8Data;
  20. }
  21. uint8_t USART0ReceiveByte()
  22. {
  23. // Wait for byte to be received
  24. while(!(UCSR0A&(1<<RXC0))){};
  25. // Return received data
  26. return UDR0;
  27. }
  28. int main (void)
  29. {
  30. uint8_t u8TempData;
  31. //Initialize USART0
  32. USART0Init();
  33.     while(1)
  34.     {
  35.         // Receive data
  36.                 u8TempData = USART0ReceiveByte();
  37.                 // Increment received data
  38.                 u8TempData++;
  39.                 //Send back to terminal
  40.         USART0SendByte(u8TempData);
  41.     }
  42.  
  43.  
  44.  


Код: Bash
  1. dimt@dimt-Satellite-L670 ~/arduino $ echo 87 > /dev/ttyACM0
  2. dimt@dimt-Satellite-L670 ~/arduino $ echo 10 > /dev/ttyACM0
  3. dimt@dimt-Satellite-L670 ~/arduino $ echo 9 > /dev/ttyACM0
  4. dimt@dimt-Satellite-L670 ~/arduino $ echo 1 > /dev/ttyACM0
  5. dimt@dimt-Satellite-L670 ~/arduino $ echo 2 > /dev/ttyACM0
  6. dimt@dimt-Satellite-L670 ~/arduino $ echo 3 > /dev/ttyACM0
  7.  
  8. // output
  9.  
  10. dimt@dimt-Satellite-L670 ~/arduino $ cat /dev/ttyACM0
  11. 87
  12. 10
  13. 9
  14. 1
  15. 2
  16. 3
  17.  

Брадъре идея знам, че имаш :)
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 10 Ноември 2016, 20:44:08
Ако искаш това, което е получено да го пишеш като ехо обратно, то трябва примерно този ред
Код: C
  1. interpretCmd(lineBuffer);
да замениш с този
Код: C
  1. printf("echo: %s\n", lineBuffer);

Ако искаш да правиш нещо друго с получените данни, то ще трябва да си имплементираш една функция, която да обработва полученото. ISR не е функция, която може да викаш в кода. Тя е независима от него и се изпълнява автоматично всеки път когато микриконтролера получи един байт. Т.е. микроконтролера прекъсва изпълнението на твоя код (това ще е най-вероятно някъде в main loop-а), скача в тази функция и изпълнява каквото има да се изпълнява в нея. И после се връща на същото място, на което изпълнението на кода е било прекъснато и то продължава. За това е важно тези ISR функции да са възможно най-кратки и нямаш право да от тях да викаш други функции осланящи се на inerrupt-и като sleep.

Примерно можеш да направиш sensorData глобална променлива и така тя ще е достъпна и в interpretCmd.
Код: C
  1. void interpretCmd(char *line)
  2. {
  3.    if(line == 0 || strlen(line) == 0) {
  4.       return;
  5.    }
  6.    
  7.    int reading= atol(line);   // обръщаме стринга в интиджър
  8.    printf("mV: %d reading: %d\n", (int)(round(sensorData)), reading); // sensorData може да я ползваме щото е глобална
  9. }

Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 10 Ноември 2016, 21:10:51
Цитат
interpretCmd(lineBuffer);
Компилатора изплю някаква грешка снощи, за тва и съм я коментирал в кода. Да не би да е част от някаква библиотека дето трябва да инклудна в хедъра? Не знаех, че ISP() - то e някаква по-специална от другите :)
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 10 Ноември 2016, 21:50:44
Цитат
Т.е. микроконтролера прекъсва изпълнението на твоя код (това ще е най-вероятно някъде в main loop-а), скача в тази функция и изпълнява каквото има да се изпълнява в нея
Това абсолютно неприемливо за мен. Имам награветели на водаата, които се управляват от сензори. Ако кода прекъсне дори за половин час, при минус 20 на вън водата в тръбата през която вземам вода от езерото може да замръзне. Нека все пак да повторя каква е целта още веднъж......

Веднъж на две седмици ходим на къщата, която е извън Торонто, средно около 2 часа от него. В момента имам 3 основни хардуерни устройства вързани към Ардуино:

1. 70 feet подгравящ кабел който е вътре в тръбата 1-1/4" през която вземам вода от езерото, това е най-важното устройство за мен през зимата.

2. Сложих и още един около тази част от тръбата която излиза извън земята и влиза в водата, той ще се стартира само когата външната температура падне под -10 и надолу.

3. Фърниса (парното е на нафта) в момента съм го направил така, че да се стартира когато температурата в къщата падне под 37F. Идеята тук е да се поддържа над минусова температура за да не замръзват тръбите  в къщата както и тези в cross space-a. Там имам помпи, бойлери, разширителни съдове и други съоражения. През зимата не се отоплявам с парното, защото имам камина на дърва. Къщата става баня след час с нея обаче..... идеята е преди да тръгна ако е много студено навън да го стартирам отдалечено докато пристигна за това искам ако е възможно тази стойност от 37F да се override-не към 60F,  но само когато пожелая това.

4. Имам и джакузи и температурата е сетната на 40F за да не се заледява  водата. При много студено време би било добра идея да мога и него да го стартирам отдалечено когато температурата е много ниска и се изисква повече време за затоплянето на водата, но това не е с приоритет.

5. Имам и photo cell sensor който връща стойности към ардуино и съответно се пускат лаптите на porch-a когато се стъмни навън.

Това е май за сега, всичко е тествано, работи  и се управлява от едно място. Идеята с флашването на майкроконтролера е неприемлива  също, понеже ре-сетва хардуера за части от секундата. Идеята да пращам стрингове през UART е най-доброто което виждам за момента.     

 
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 11 Ноември 2016, 17:22:43
Нещо не си ме разбрал явно. Прекъсването за което споменах е с продължителност частици от секундата. Няма как и да е по друг начин. Ти си нагласил примерно UART да работи с 9600 baud и си казал, че пращаш/приемаш по 8 бита на симво с 1 стартов бит и 1 стоп-бит -> 10 бита на символ. Това означава, че можеш да изпращаш и приемаш по 960 символа на секунда.
960 bytes per 1000 millisec -> Максималното ти забавяне, което можеш да си позволиш в ISR e 1000/960 = 1.04 миллисекунди.

Ето примерно в този код, който си дал като работещ
Код: C
  1. uint8_t USART0ReceiveByte()
  2. {
  3.    // Wait for byte to be received
  4.    while(!(UCSR0A&(1<<RXC0))){};
  5.    // Return received data
  6.    return UDR0;
  7. }

този ред блокира програмата ти докато не дойде един байт
Код: C
  1.  while(!(UCSR0A&(1<<RXC0))){};

Значи докато не изпратиш няква команда към контролера, той си чака на този ред.

Като ползваш interrupt, main-loopa си върви и се прекъсва само тогава, когато е получен от някъде 1 байт.

А interpretCmd беше само пример. Функцията трябва сам ди се я дефинираш.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 11 Ноември 2016, 17:51:41
Добре. Ще видя какво ще сътворя по-късно, че съм на работа в момента. Щом мога да пращам стринг през UART и да го обръщам в int мисля, че това ще ми свърши работа.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 11 Ноември 2016, 23:22:57
Браткиш, виж тва видео - https://www.youtube.com/watch?v=WIetgFpGzfQ&index=11&list=PLA6BB228B08B03EDD

Когато прати "1" през терминала той пали пина, когато прати "0" го чисти. Ся кът се замисля, тво тва ми трябва и на мен. Примерно преди да тръгна за къщата го паля с 1 и когато температурата стигне определената от мен граница (и да речем още съм на пътя) програмата да хвърля 0 и да чисти порта. Кво мислиш за идеята? 
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 12 Ноември 2016, 01:51:41
Стана.  Поствам кода. Може пък да потрябва на някой ентусиаст като мен :)

Код: C
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <avr/io.h>
  4. #include <util/delay.h>
  5. #include <avr/interrupt.h>
  6.  
  7. #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  8. #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  9.  
  10. #define F_CPU 16000000UL
  11. #define BUAD 9600
  12. #define BRC (((F_CPU / (BUAD * 16UL))) - 1)
  13.  
  14. #define RX_BUFFER_SIZE 50
  15. #define ADC_AIR_CHANNEL 0
  16. #define NUM_READINGS 10
  17.  
  18. #define PORT_ON(port,pin) port |= (1<<pin)
  19. #define PORT_OFF(port,pin) port &= ~(1<<pin)
  20.  
  21. char rxBuffer[RX_BUFFER_SIZE];
  22. uint8_t rxReadPos = 0;
  23. uint8_t rxWritePos = 0;
  24.  
  25. // declare all functtions
  26. void USART0Init(void);
  27. void USART0SendByte(char u8Data, FILE *stream);
  28. void InitADC(void);
  29. uint16_t ReadADC(uint8_t ADCchannel);
  30. float ReadAiremp(uint8_t channel,  uint16_t *values_of__air, int sizeOfValues);
  31. char getChar(void);
  32. char peekChar(void);
  33.  
  34. void USART0Init(void) {
  35.         // Set baud rate
  36.     UBRR0H = (BRC >> 8);
  37.     UBRR0L =  BRC;  
  38.      
  39.     UCSR0B = (1 << RXEN0)  | (1 << RXCIE0) |(1<<TXEN0);
  40.  
  41.     UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
  42. }
  43.  
  44. void USART0SendByte(char u8Data, FILE *stream) {
  45.         if(u8Data == '\n')
  46.         {
  47.             USART0SendByte('\r', stream);
  48.         }
  49.         //wait while previous byte is completed
  50.         while(!(UCSR0A&(1<<UDRE0))){};
  51.         // Transmit data
  52.         UDR0 = u8Data;
  53. }
  54.  
  55. //set stream pointer
  56. FILE usart0_str = FDEV_SETUP_STREAM(USART0SendByte, NULL, _FDEV_SETUP_WRITE);
  57.  
  58. void InitADC(void) {
  59.         // Select Vref=AVcc
  60.         ADMUX |= (1<<REFS0);
  61.         //set prescaller to 128 and enable ADC
  62.         ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADEN);    
  63. }
  64.      
  65. uint16_t ReadADC(uint8_t ADCchannel) {
  66.  
  67.         //select ADC channel with safety mask
  68.         //single conversion mode
  69.         while( ADCSRA & (1<<ADSC) );
  70.        
  71.          //select ADC channel with safety mask
  72.          ADMUX = (ADMUX & 0xF0) | (ADCchannel & 0x0F);
  73.  
  74.         // start single convertion
  75.         // write ’1′ to ADSC
  76.         ADCSRA |= (1<<ADSC);
  77.  
  78.   // wait for conversion to complete
  79.   // ADSC becomes ’0′ again
  80.   // till then, run loop continuously
  81.   while(ADCSRA & (1<<ADSC));
  82.  
  83.   return (ADC);
  84. }
  85.  
  86. float ReadAirTemp(uint8_t channel,  uint16_t *values_of__air, int sizeOfValues) {
  87.         int i = 0;
  88.         int  total = 0;
  89.         float average = 0.0f;
  90.  
  91. for (i = 0; i < sizeOfValues; i++) {
  92.  
  93.         values_of__air[i] = ReadADC(channel); // тука може да ползваме функцията ReadADC,защото
  94.                                               // тя вече е декларирана най-отгоре и е позната
  95.         total = total + values_of__air[i];    // няма нужда от екстра loop за сбора
  96.  
  97.         _delay_ms(300);
  98.  }
  99.  
  100.         average = (float)total / (float)sizeOfValues;
  101.  
  102.         return average;
  103. }
  104.  
  105. int main(void) {
  106.     //initialize USART0Init
  107.     USART0Init();
  108.  
  109.     //initialize ADC
  110.     InitADC();
  111.    
  112.     // set port B pin 0 as output
  113.     DDRB = (1 << PORTB0);
  114.  
  115.     //assign our stream to standard I/O streams
  116.     stdout = &usart0_str;
  117.    
  118.     uint16_t values_of__air[NUM_READINGS] = {0};
  119.    
  120.     float tmp_air = 0.0f;
  121.        
  122.     sei();
  123.      
  124.     while(1)
  125.     {
  126.  
  127.         tmp_air = ReadAirTemp(ADC_AIR_CHANNEL, values_of__air, NUM_READINGS);
  128.  
  129.         printf("Air Temperature: %d\n", (int)(round(tmp_air)));
  130.        
  131.         char c = getChar();
  132.          
  133.         if(c == '1')
  134.         {
  135.             sbi(PORTB, PORTB0);
  136.         }
  137.         else if(c =='0')
  138.         {
  139.             cbi(PORTB, PORTB0);
  140.         }
  141.     }
  142. }
  143.  
  144. char peekChar(void)
  145. {
  146.     char ret = '\0';
  147.      
  148.     if(rxReadPos != rxWritePos)
  149.     {
  150.         ret = rxBuffer[rxReadPos];
  151.     }
  152.      
  153.     return ret;
  154. }
  155.  
  156. char getChar(void)
  157. {
  158.     char ret = '\0';
  159.      
  160.     if(rxReadPos != rxWritePos)
  161.     {
  162.         ret = rxBuffer[rxReadPos];
  163.          
  164.         rxReadPos++;
  165.          
  166.         if(rxReadPos >= RX_BUFFER_SIZE)
  167.         {
  168.             rxReadPos = 0;
  169.         }
  170.     }
  171.      
  172.     return ret;
  173. }
  174.  
  175. ISR(USART_RX_vect)
  176. {
  177.     rxBuffer[rxWritePos] = UDR0;
  178.      
  179.     rxWritePos++;
  180.      
  181.     if(rxWritePos >= RX_BUFFER_SIZE)
  182.     {
  183.         rxWritePos = 0;
  184.     }
  185. }
  186.  

//output

Код: Bash
  1. Air Temperature: 146
  2. Air Temperature: 146
  3. Air Temperature: 146
  4. Air Temperature: 146
  5. Air Temperature: 146
  6. Air Temperature: 146
  7. Air Temperature: 146
  8. Air Temperature: 146
  9. Air Temperature: 146
  10. Air Temperature: 146
  11. Air Temperature: 146
  12. Air Temperature: 146
  13. Air Temperature: 146
  14. Air Temperature: 146
  15. Air Temperature: 146
  16. Air Temperature: 146
  17.  
  18. // send 1 bit / clear it up
  19.  
  20. dimt@dimt-Satellite-L670 ~/arduino $ echo 1 > /dev/ttyACM0
  21. dimt@dimt-Satellite-L670 ~/arduino $ echo 0 > /dev/ttyACM0
  22.  
  23.  
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 12 Ноември 2016, 11:32:45
Кода изглежда добре с няколко забележки.
1. Твоят микроконтролер не може да е на 16MHz, освен ако не си закачил външен кварц към него. Ако си нагласял fuses максимума ти е 8MHz.
2. Указателите към опашхата и главата на ring buffer-а трябва да са задължително декларирани volatile, тъй като са глобални променливи, които биват модифицирани в interrupt.
Код: C
  1. volatile uint8_t rxReadPos = 0;
  2. volatile uint8_t rxWritePos = 0;
3. Имаш непокрит случай, когато пишещият указател надмине четящия.
4. Команди съставени от един символ работят в твоя случай, но ако решиш да добавиш допълнително други команди/функции ще стане мъка. Примерно както си ги изброил в предния пост можеш да имаш команди от сорта на
Код: Text
  1. furnace=1         // включваш фърниса
  2. furnace=0         // изключваш фърниса
  3. hottub=temp       // проверяваш температурата на джакузито
  4. hottub=1          // загряваш джакузито
  5. hottub=0          // изключваш нагревателя на джакузито
  6. lights=porch,1    // включваш лампите на верандата
  7. lights=porch,0    // изключваш лампите на верандата
  8. ....
По този начин може да си направиш не само автоматизация, но и команден интерфейс през web примерно. Или за смартфона през BT/Wi-Fi.
 
Освен това може да се оптимизира програмата доста. Примерно ти правиш 10 четения с по 300 милисекунди пауза между тях, което означава, че main loop-a проверява каква е температурата на приблизително всеки 3 секунди. Е па колко да се е променила за това време таз температура?  ;D

Ако ти се чете и занимава можеш да направиш нещо подобно на това
Код: Text
  1. while(1)
  2. {
  3.     вземи актуална температура
  4.     реагирай ако трябва според прочетената температура
  5.     ако е получена команда я интерпретирай
  6.     постави микроконтролера в deep sleep за Х секунди
  7. }

Поставяйки контролера в deep sleep той не консумира почти никаква енергия. Бива събуден от интеръпт след X секунди, което е смисления интервал за проверка на температурата, или от интеръпт генериран от получена uart команда.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 12 Ноември 2016, 13:27:02
Цитат
1. Твоят микроконтролер не може да е на 16MHz, освен ако не си закачил външен кварц към него. Ако си нагласял fuses максимума ти е 8MHz.

До 20MHz го дават - http://www.atmel.com/devices/atmega328.aspx

Цитат
2. Указателите към опашхата и главата на ring buffer-а трябва да са задължително декларирани volatile, тъй като са глобални променливи, които биват модифицирани в interrupt.
Оправих го :)

Цитат
3. Имаш непокрит случай, когато пишещият указател надмине четящия.
Не се ли обезмисля тази проверка, при положение, че когато буфера се напълни rxRead and rxWritePos се сетват към 0 ?

Цитат
Команди съставени от един символ работят в твоя случай, но ако решиш да добавиш допълнително други команди/функции ще стане мъка. Примерно както си ги изброил в предния пост можеш да имаш команди от сорта на..... По този начин може да си направиш не само автоматизация, но и команден интерфейс през web примерно. Или за смартфона през BT/Wi-
Мога да го направя - 1 / 0 за фърниса, 2 / 3 за джакузито примерно. Напълно съгласен съм, че може да се направи един добър графичен апликейшън да пали устройствата през мрежата, но и един прост терминал ме устройва за момента :)

Цитат
Поставяйки контролера в deep sleep той не консумира почти никаква енергия. Бива събуден от интеръпт след X секунди, което е смисления интервал за проверка на температурата, или от интеръпт генериран от получена uart команда.
Тва е интересно. Ще потърся инфо и шъ та ъпдейтвам ;) 


Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 12 Ноември 2016, 14:06:15
До 20MHz го дават - http://www.atmel.com/devices/atmega328.aspx

Това е максимална стойност при използване на външен кварц. До колкото разбрах от предните ти постове (http://nau4i.me/forum/index.php/topic,16672.msg50658.html#msg50658), ти използваш вградения RC oscilator, който има максимум от 8Mhz, но е конфигуриран за 1MHz.

Ардуиното ти има ектра кварц, който е на 16MHz.
(http://image.slidesharecdn.com/arduinoslidesneopixels-150202100723-conversion-gate01/95/arduino-slides-with-neopixels-11-638.jpg)

Ако ти е интересно защо в това  (https://www.youtube.com/watch?v=DHwt_ioVavEDHwt_ioVavE)видео един тинейджър ги съпоставя.


Не се ли обезмисля тази проверка, при положение, че когато буфера се напълни rxRead and rxWritePos се сетват към 0 ?
Не се обезмисля, защото пишещия указател се инкрементира от interrupt. Т.е променя се асинхронно. Това значи, че може преди да си прочел съдържанието на буфера, той да се е напълнил.

Примерно, както ти бях писал вече, имаш 9600 baud с 1 стартов и 1 стоп бит, което  означава, че може да получиш 960 знака в секунда. Твоят буфер е с капацитет 50. Четенето на температурата ти отнема 3 секунди.
Т.е. ти преди да стигнеш до реда, в който четеш един единствен знак от буфера
Код: C
  1. char c = getChar();

може вече да си получил до 2880 символа (3сек * 960 символа). Къде къде повече от размера на буфера ти. Тъй като не проверяваш дали пишещият указател не е настигнал четящия, ти ще презапишеш стойностите на целия буфер 57 пъти.

Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 12 Ноември 2016, 14:46:49
Взех едно ардуино преди няколко дни на много тънка цена за да мога да правя тестове през UART докато пристигне обръщача, а пък да имам и back-up ако стане нещо с това на къщата. Айде...... излизам, че работя този weekend ;)
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 12 Ноември 2016, 19:52:49
Интересен репорт получих тази сутрин в 7. Направил съм скрипт да ми праща температурата и ежедневният трафик на джаджата която ползвам:

Код: Bash
  1. ipaddress: 184.151.37.61
  2. Water Temperature: 75
  3. Outside Temperature: 47
  4. Cottage Temperature: 87
  5.  eth0  /  daily
  6.        day                  rx        |     tx            |    total         |   avg. rate
  7.       11/01/16        73 KiB |     364 KiB |     437 KiB |    0.04 kbit/s
  8.       11/02/16        69 KiB |     401 KiB |     470 KiB |    0.04 kbit/s
  9.       11/03/16        70 KiB |     362 KiB |     432 KiB |    0.04 kbit/s
  10.       11/04/16      5.04 MiB |    1.28 MiB |    6.32 MiB |    0.60 kbit/s
  11.       11/05/16     24.57 MiB |    3.34 MiB |   27.92 MiB |    2.65 kbit/s
  12.       11/06/16      7.34 MiB |     765 KiB |    8.09 MiB |    0.77 kbit/s
  13.       11/07/16        87 KiB |      86 KiB |     173 KiB |    0.02 kbit/s
  14.       11/08/16       108 KiB |     108 KiB |     216 KiB |    0.02 kbit/s
  15.       11/09/16        90 KiB |      89 KiB |     179 KiB |    0.02 kbit/s
  16.       11/10/16       111 KiB |     109 KiB |     220 KiB |    0.02 kbit/s
  17.       11/11/16       108 KiB |     162 KiB |     270 KiB |    0.03 kbit/s
  18.       11/12/16        30 KiB |      30 KiB |      60 KiB |    0.02 kbit/s
  19.  

Изглежда кабела в тръбата се е включвал вчера. Сутринта беше -5 на къщата.

Данните които се връщат са в mV. За да се изчисли температурата в Fahreinheit, формулата е ( примерно водата) - 75*(5000/1024)/10
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 12 Ноември 2016, 20:21:21
Това от сензора ли са данни? И ако да, какъв сензор ползваш?
Ако е TMP36, то формулата изглежда да е
(mV - 500) / 10 (https://learn.adafruit.com/tmp36-temperature-sensor/using-a-temp-sensor)
Или в твоя случай
( (75 * (5000 / 1024))  - 500 ) /10 или -13.37°C, което ми се вижда голям студ  ;D
 
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 12 Ноември 2016, 22:17:51
С LM34 съм. Тва е стойноста идваща от analog output voltage пина- http://www.learningaboutelectronics.com/Articles/LM34-temperature-sensor-circuit.php

Никога не съм го мерил директно.

С таз калкулация по-горе, нема да ми стигне заплатата тока да си платя  :)   
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 13 Ноември 2016, 09:50:48
А каква ти е горната граница? Т.е. след като си пуснал кабела да нагрява кога го спираш?
Дай малко повече информация де, стига си я стискал. :)
Какви сензори си включил (модел), с реле ли превключваш (модел)? Покажи как си ги навързал (схема или снимка).
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 13 Ноември 2016, 14:50:42
Цитат
А каква ти е горната граница? Т.е. след като си пуснал кабела да нагрява кога го спираш?
Падне ли температурата под 36F нагревателят стартира, над тази температура не работи.

Цитат
Дай малко повече информация де, стига си я стискал. :)
Миналата година точно на Нова Година отидохме  с приятели за да я посрещнем там и се оказахме неприятно изненадани без вода, водата беше замръзнала в тръбата. Последният път когато бях на къщата беше някъде през Октомври, след това претърпях злополука и не бях ходил повече от месец и половина заа да я нагледам. Някъде по това време (Ноември) температурите са били паднали под 0-та, термостата към нагревателят е бил изтрещял и водата беше замръзнала. Предишният собственик е източвал водата от тръбата като го е зазимявал, но преди него хора са живели там и през зимата. Дойде Април. Времето стана топло и направих опит да измъкна кабела от тръбата но без успех (смятай как е бил замръзнал). Срязах го от едната страна и го вързах директно към тока. Точно след 10 минути кабела почна да играе в тръбата и успях да го измъкна. И от там започна всичко. Първоначално реших да купя Digital Heating Thermostat и дори купих този - https://www.amazon.ca/RioRand-Thermostat-Temperature-Controller-Waterproof/dp/B00KCCX0EE. По-късно се заамислих и реших да взема едно Ардуино и да централизирам целият процес и не съжалявам, че се спрях на него.  Направих нов накрайник на heating cable-a, който да бъде water-proof и също да може издържа и на температура. След това трябваше да купя сензор, спрях се на LM35 понеже прочетох по форуми, че работи добре с Ардуно, но се оказа, че тук по-лесно се намира LM 34.  Пробих тръбата за да инсталирам сензора за да мери темп на воодата. Направих го и него water-proof, залях го с epoxy в един пластмасов плъг на резба и го завъртях към тръбата, която представлява едно дебело и дълго парче PVC. Купих  от ebay едно 10amp SSR relay DC/AC. Тока минаваш през кабела е около 4.3 amp, около 500w e. Би трябвало да свърши работа, все пак водата няма да я правя на чай я. Отделно имам около 10 feet-а PVC което излиза от земята преди да влезнее във водата. За тази част реших да купя кабел който се усуква външно, около тръбата. Увих го в изолация и нанизах още една тръба 2" широка. Него съм решил да го пускам, когато външната температура падне под 14F. Toй е с мощност около 125 w. И така... едно по едно нещата почнаха да си идват на мястото . За подаване / вземaнe на ниското напрежение ползвам cat 5 ethernet cable. В крайна сметка в момента имам 4 темп. сензора, един photocell и две SSR от което едното е 4 way channel на Omron - https://www.amazon.ca/SavvyTec-Channel-Solid-state-Relay-Trigger/dp/B01M1HQSTG/ref=sr_1_15?s=electronics&ie=UTF8&qid=1479039721&sr=1-15&keywords=Omron+ssr. Arduino и него съм ги сложил в box и въобще е много прибрано всичко и лесно за поддръжка. За джакузиито още не съм решил дали си струва да го командвам и него (макар, че имам всичко), понеже много ток самото то консумира през зимата а и похлупака му не е хич хубав и изтича много heat през него, тва е и една от причините. Но както казах  в един друг пост, най-важното нещо е тръбата и водата в нея да се отопляват. Тук шега с температурите не бива. А .....забравих да спомена нещо важно. Понеже сензорите са на голямо разтояние от Ардуино при мен, за да стабилизирам сигнала (който е представен в mV) беше необходимо да сложа10k / 11k съпротивление на изхода.  По този начин няма остатъчно напрежение по трасето, без него напрежението играеше много яко ;)
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 13 Ноември 2016, 18:44:01
Само гледай да няма рибена чорба  ;D
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 13 Ноември 2016, 21:40:32
Брадъре, нещо странно се случва. След 8-ят, 9-ят принтф пина се пали сам. Забелязах, че ако стойноста е 141 последната 1-ца го пали, ако стане  140 го чисти. Получава се някакво сбиване очевидно. Ако махна printf() всичко работи както трябва. Идея да имаш как да го фиксна  ;)
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 14 Ноември 2016, 10:14:53
Дай да видим целия код. Или е този който постна последно?
Много ме съмнява да има нещо общо с това дали е 140 или 141.

Добави следното към принта и дай да видим изхода около момента когато се скофтят нещата.
Код: C
  1. printf("Air Temperature: %d, rxr=%u, rxw=%u, c=%02X\n", (int)(round(tmp_air)), rxReadPos, rxWritePos, (uint8_t)rxBuffer[rxReadPos]);
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 14 Ноември 2016, 13:24:27
Всичко е нормално, но не мога да подпаля пина. Ако коментирам printf() паля пина но пък няма изход а тва е важно за мен за да знам каква е текущата теемпература.

Тва  е изхода:
Код: Bash
  1. Air Temperature: 139, rxr=0, rxw=0, c=00
  2.  
  3. Air Temperature: 139, rxr=0, rxw=0, c=00
  4.  
  5. Air Temperature: 139, rxr=1, rxw=44, c=69
  6.  
  7. Air Temperature: 139, rxr=2, rxw=39, c=65
  8.  
  9. Air Temperature: 139, rxr=3, rxw=34, c=65
  10.  
  11. Air Temperature: 139, rxr=4, rxw=29, c=2C
  12.  
  13. Air Temperature: 139, rxr=5, rxw=24, c=34
  14.  
  15. Air Temperature: 139, rxr=6, rxw=19, c=3D
  16.  
  17. Air Temperature: 139, rxr=7, rxw=14, c=3D
  18.  
  19. Air Temperature: 139, rxr=8, rxw=9, c=0A
  20.  
  21. Air Temperature: 139, rxr=9, rxw=3, c=41
  22.  
  23. Air Temperature: 139, rxr=10, rxw=47, c=70
  24.  
  25. Air Temperature: 139, rxr=11, rxw=43, c=65
  26.  
  27. Air Temperature: 139, rxr=12, rxw=39, c=39
  28.  
  29. Air Temperature: 139, rxr=13, rxw=35, c=72
  30.  
  31. Air Temperature: 139, rxr=14, rxw=34, c=20
  32.  
  33. Air Temperature: 139, rxr=15, rxw=30, c=78
  34.  
  35. Air Temperature: 139, rxr=16, rxw=26, c=2C
  36.  
  37. Air Temperature: 139, rxr=17, rxw=22, c=43
  38.  
  39. Air Temperature: 139, rxr=18, rxw=18, c=0D
  40.  
  41. Air Temperature: 139, rxr=19, rxw=14, c=69
  42.  
  43. Air Temperature: 139, rxr=20, rxw=10, c=6D
  44.  

 Кода е този:

Код: C
  1.  
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <avr/io.h>
  5. #include <util/delay.h>
  6. #include <avr/interrupt.h>
  7.  
  8. #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  9. #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
  10.  
  11. #define F_CPU 16000000UL
  12. #define BUAD 9600
  13. #define BRC (((F_CPU / (BUAD * 16UL))) - 1)
  14.  
  15. #define RX_BUFFER_SIZE 50
  16. #define ADC_AIR_CHANNEL 0
  17. #define NUM_READINGS 10
  18.  
  19. #define PORT_ON(port,pin) port |= (1<<pin)
  20. #define PORT_OFF(port,pin) port &= ~(1<<pin)
  21.  
  22. char rxBuffer[RX_BUFFER_SIZE];
  23. volatile uint8_t rxReadPos = 0;
  24. volatile uint8_t rxWritePos = 0;
  25.  
  26. // declare all functtions
  27. void USART0Init(void);
  28. void USART0SendByte(char u8Data, FILE *stream);
  29. void InitADC(void);
  30. uint16_t ReadADC(uint8_t ADCchannel);
  31. float ReadAirTemp(uint8_t channel,  uint16_t *values_of__air, int sizeOfValues);
  32. char getChar(void);
  33. char peekChar(void);
  34.  
  35. void USART0Init(void) {
  36.  
  37.     // Set baud rate
  38.     UBRR0H = (BRC >> 8);
  39.  
  40.     UBRR0L =  BRC;  
  41.      
  42.     UCSR0B = (1 << RXEN0)  | (1 << RXCIE0) | (1<<TXEN0);
  43.  
  44.     UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
  45.  
  46. }
  47.  
  48. void USART0SendByte(char u8Data, FILE *stream) {
  49.         if(u8Data == '\n')
  50.         {
  51.             USART0SendByte('\r', stream);
  52.         }
  53.         //wait while previous byte is completed
  54.         while(!(UCSR0A&(1<<UDRE0))){};
  55.         // Transmit data
  56.         UDR0 = u8Data;
  57. }
  58.  
  59. //set stream pointer
  60. FILE usart0_str = FDEV_SETUP_STREAM(USART0SendByte, NULL, _FDEV_SETUP_WRITE);
  61.  
  62. void InitADC(void) {
  63.         // Select Vref=AVcc
  64.         ADMUX |= (1<<REFS0);
  65.         //set prescaller to 128 and enable ADC
  66.         ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)|(1<<ADEN);    
  67. }
  68.      
  69. uint16_t ReadADC(uint8_t ADCchannel) {
  70.  
  71.         //select ADC channel with safety mask
  72.         //single conversion mode
  73.         while( ADCSRA & (1<<ADSC) );
  74.        
  75.          //select ADC channel with safety mask
  76.          ADMUX = (ADMUX & 0xF0) | (ADCchannel & 0x0F);
  77.  
  78.         // start single convertion
  79.         // write ’1′ to ADSC
  80.         ADCSRA |= (1<<ADSC);
  81.  
  82.   // wait for conversion to complete
  83.   // ADSC becomes ’0′ again
  84.   // till then, run loop continuously
  85.   while(ADCSRA & (1<<ADSC));
  86.  
  87.   return (ADC);
  88. }
  89.  
  90. float ReadAirTemp(uint8_t channel,  uint16_t *values_of__air, int sizeOfValues) {
  91.         int i = 0;
  92.         int  total = 0;
  93.         float average = 0.0f;
  94.  
  95. for (i = 0; i < sizeOfValues; i++) {
  96.  
  97.         values_of__air[i] = ReadADC(channel); // тука може да ползваме функцията ReadADC,защото
  98.                                               // тя вече е декларирана най-отгоре и е позната
  99.         total = total + values_of__air[i];    // няма нужда от екстра loop за сбора
  100.        
  101.         _delay_ms(300);
  102.  }
  103.         average = (float)total / (float)sizeOfValues;
  104.        
  105.         return average;
  106. }
  107.  
  108. int main(void) {
  109.     //initialize USART0Init
  110.     USART0Init();
  111.  
  112.     //initialize ADC
  113.     InitADC();
  114.    
  115.     // set port B pin 0 as output
  116.     DDRB = (1 << PORTB0);
  117.  
  118.     //assign our stream to standard I/O streams
  119.     stdout = &usart0_str;
  120.    
  121.     uint16_t values_of__air[NUM_READINGS] = {0};
  122.    
  123.     float tmp_air = 0.0f;
  124.        
  125.     sei();
  126.      
  127.     while(1)
  128.     {
  129.  
  130.         tmp_air = ReadAirTemp(ADC_AIR_CHANNEL, values_of__air, NUM_READINGS);
  131.        
  132.        // printf("Temperature: %d\n", (int)(round(tmp_air)));  
  133.         //printf("Air Temperature: %d, rxr=%u, rxw=%u, c=%02X\n", (int)(round(tmp_air)), rxReadPos, rxWritePos, (uint8_t)rxBuffer[rxReadPos]);
  134.         char c = getChar();
  135.          
  136.         if(c == '1')
  137.         {
  138.             sbi(PORTB, PORTB0);
  139.         }
  140.         else if(c == '0')
  141.         {
  142.             cbi(PORTB, PORTB0);
  143.         }
  144.     }
  145. }
  146.  
  147. char peekChar(void)
  148. {
  149.     char ret = '\0';
  150.      
  151.     if(rxReadPos != rxWritePos)
  152.     {
  153.         ret = rxBuffer[rxReadPos];
  154.     }
  155.      
  156.     return ret;
  157. }
  158.  
  159. char getChar(void)
  160. {
  161.     char ret = '\0';
  162.      
  163.     if(rxReadPos != rxWritePos)
  164.     {
  165.         ret = rxBuffer[rxReadPos];
  166.          
  167.         rxReadPos++;
  168.          
  169.         if(rxReadPos >= RX_BUFFER_SIZE)
  170.         {
  171.             rxReadPos = 0;
  172.         }
  173.     }
  174.      
  175.     return ret;
  176. }
  177.  
  178. ISR(USART_RX_vect)
  179. {
  180.     rxBuffer[rxWritePos] = UDR0;
  181.      
  182.     rxWritePos++;
  183.      
  184.     if(rxWritePos >= RX_BUFFER_SIZE)
  185.     {
  186.         rxWritePos = 0;
  187.     }
  188. }
  189.  
  190.  
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 14 Ноември 2016, 14:54:11
Е па кво му е нормалното?  ???
Не виждаш ли, че пишещия и четящия указател на буфера с получени знаци здравата са се разшавали. А в буфера има някви боклуци, които може по някаква случайност от време на време да са '1', или '0'.

Преди да подкараш паленето на пина се увери , че имплементацията на UART ти е правилна. Т.е. направи си ехо и се увери, че това, което си написал/изпратил през uart, е това което микроконтролера получава. Нищо друго не трябва да пълни буфера. Ако да речем пратиш 'F' в буфера трябва да има само и единствено символа 'F'!

Код: C
  1. while(1)
  2. {  
  3.     char c = getChar();
  4.     if(c != 0) {
  5.        printf("got: %c\n", c);
  6.     }
  7. }

Едит:
между другото бих ти препоръчал поне за тестовете да използваш minicom, hterm, или picocom.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 14 Ноември 2016, 20:20:23
Добре. Шъ видя кво мога да направя сам и ще пиша ;)


PS: Виж кво става като пусна 1:

Цитат
dimt@dimt-Satellite-L670 ~ $ cat /dev/ttyACM0

got: 1

got:


got:



got: g

got: o

got:


got:



got: g

got: o

got: t

got:


Код: C
  1. while(1)
  2.     {
  3.  
  4.         tmp_air = ReadAirTemp(ADC_AIR_CHANNEL, values_of__air, NUM_READINGS);
  5.  
  6.          // printf("Temperature: %d\n", (int)(round(tmp_air)));  
  7.         //printf("Air Temperature: %d, rxr=%u, rxw=%u, c=%02X\n", (int)(round(tmp_air)), rxReadPos, rxWritePos, (uint8_t)rxBuffer[rxReadPos]);
  8.         char c = getChar();
  9.  
  10.        if(c != 0) {
  11.        printf("got: %c\n", c);
  12.        }
  13.         if(c == '1')
  14.         {
  15.             sbi(PORTB, PORTB0);
  16.         }
  17.         else if(c == '0')
  18.         {
  19.             cbi(PORTB, PORTB0);
  20.         }
  21.     }
  22. }
  23.  
  24.  
  25.  
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 14 Ноември 2016, 21:55:01
Забелязах нещо интереснно също. Ако ползвам screen /dev/ttyACM0 проблем нямам. Всъщност тва е и програмата която ползвам за да извличам екото от микропроцесора и след товва да ми се праща репорт на всеки 12 часа. Обаче ако искам да видя изхода с cat /devt/tyACM0 се получава АКОТО :)

Виж същият изход но през screen, пина е сетнат към 1:

Код: Bash
  1. Air Temperature: 142, rxr=2, rxw=2, c=00
  2. Air Temperature: 143, rxr=2, rxw=2, c=00
  3. Air Temperature: 142, rxr=2, rxw=2, c=00
  4. Air Temperature: 142, rxr=2, rxw=2, c=00
  5. Air Temperature: 142, rxr=2, rxw=2, c=00
  6. Air Temperature: 142, rxr=2, rxw=2, c=00
  7. Air Temperature: 142, rxr=2, rxw=2, c=00
  8. Air Temperature: 142, rxr=2, rxw=2, c=00
  9. Air Temperature: 142, rxr=2, rxw=2, c=00
  10. Air Temperature: 142, rxr=2, rxw=2, c=00
  11. Air Temperature: 142, rxr=2, rxw=2, c=00
  12.  
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 14 Ноември 2016, 22:18:36
Най-добре както ти писах вече е да се свържш през minicom и да видиш дали не идват някви символи без да си пращал нищо. И дали ако пратиш символ ще получиш само и единствено ехо с този символ.

Код: Bash
  1. minicom -b 9600 -D /dev/ttyACM0

или нещо такова
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 15 Ноември 2016, 00:24:07
Яко....не бях чувал за нея :) Да, каквото пратя това и получавам няма друго. Вече съм 100% сигурен, че  мазалото е идвало от cat.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 15 Ноември 2016, 09:31:02
Аз бих ти препоръчал да си реструктурираш четенето на температурата. Принципно едно такова блокиране на main loop за 3 секунди е неприемливо. Освен разбира се ако не е за да пестиш енергия, слагайки микроконтролера да спи през това време. Това мудно четене добавя забавяне в response time за командите, които пращаш през uart. По този начин създава предпоставка за препълване на буфера.

AD конвертора също има съответен interrupt, с който можеш да премахнеш този busy wait, с който чакаш да приключи преобразуването.
Освен това, ADC може да се конфигурира така, че да бъде викан автоматично от примерно timer1. По този начин ще направиш проверката на температурата напълно независима от останалата част от кода. И няма да блокираш main.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 15 Ноември 2016, 14:29:37
За сега няма да пипам нищо, на пролет ;) Важното е, че водата се нагрява, виждам това от репортите, които получавам. В петък ще ходим и ще бъда там за уикенда, нещото което бих добавил е само да мога да паля / гася фърниса отдалечено.   
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 22 Декември 2016, 21:31:20
Това от сензора ли са данни? И ако да, какъв сензор ползваш?
Ако е TMP36, то формулата изглежда да е
(mV - 500) / 10 (https://learn.adafruit.com/tmp36-temperature-sensor/using-a-temp-sensor)
Или в твоя случай
( (75 * (5000 / 1024))  - 500 ) /10 или -13.37°C, което ми се вижда голям студ  ;D
Брадъре, миналият четвъртък температурата навън на къщата удари -25. Обаче върнатото напрежението от сензора не показа отрицателна стойност . Което, според формулата по която изчислявам е 0*(500/1024) = 0 F = -17.77 C. Че се чудя....възможно ли е да върне отрицателна стойност (отрицателно напрежение) или с тази round функция всичко се закръгля само около 0-та?     
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 22 Декември 2016, 22:42:45
ADC-то може да работи само със стойности между 0V и 5V.
Този сензор, който използваш мери между -50°F и +300°F със резолюция от 10mV per 1°F.
Та за да замерваш температури по-ниски от 0°F, трябва да можеш да замерваш отрицателно напрежение до -500mV
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 15 Януари 2017, 18:27:39
Сложих два диода 1N914 към ground reference-a с получен voltage drop около 0.96 mV и по-този начин аналоговият ADC reading се увеличи двойно и отгоре.
Код: C
  1. outside_temp = ReadOutsideTemp(OUTSIDE_TEMP_PIN, values, NUM_READINGS)*(5000.0/1023.0-0.96)/10;
  2.  

http://www.ti.com/lit/ds/symlink/lm34.pdf (виж 8.3 system examples)
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 16 Януари 2017, 09:21:46
Аз мислех да ти предлагам да вържеш един opamp, ама си викам на него сигурно не му се занимава с такива работи :)

Трябва да имаш предвид, че стойностите които замерваш с диода не са нито точни нито константни. Voltage drop-а е по-скоро около тези 0.96V (предполага си объркал мерните единици), а не точно толкова. Ако погледнеш в data sheet-a на 1N914 (http://www.vishay.com/docs/85622/1n914.pdf) ще видиш, че за тези 75 µA, които дърпа LM34 там са посочени 0.6V drop. Та с два диода би трябвало да си около 1.2V. Но както и графиката показва това са typical стойности мерени при 25°C. При отрицателни температури forward voltage-a пада с някой друг mV на всеки °C под нулата.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 16 Януари 2017, 14:18:28
При 71F в стаята, ардуино връща стойност от 0.71 mV с LM34 и 18к resistor, както е показано в схемата по-горе. С двата диода стойноста става 1.66 mV, разликата е 0.96 mV. Да речем ако стойноста падне до 0.76 ( не съм тествал още) то тогава математиката според мен  би изгеждала така:
(0.76-0.96)*100 = -20F.
Принципно 0 по Fahrenheit си е достатъчна ниска температура за да се включва всичко ама ........ нали все нещо пипам и ъпгрейдвам :)
За  opamp си мислех в самото начало, но вече имам изградена, работеща система, която не ме предава до сега ;) 
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: kjufte в 16 Януари 2017, 23:42:25
При 71F в стаята, ардуино връща стойност от 0.71 mV с LM34 и 18к resistor, както е показано в схемата по-горе. С двата диода стойноста става 1.66 mV, разликата е 0.96 mV.
Чекай са да се разберем за тез волтажи и мили волтажи.
Сензора ако ти връща наистина 0.71mV, то значи имаш някаква кардинална грешка или в кода или в схемата. Сензора ти има резолюция от 10mV на 1°F. Та ако наистина получаваш 0.71mV, то това значи че измерваш
0.71/10 = 0.071°F
Верно ли е такъв клинч в стаята? То бива пестене да има за банката, ама чак па тлкоз :)

Затова писах, че сигурно си объркал мерните единици. Най-вероятно става въпрос за 750mV и 960mV офсет или съответно 0.75V и 0.96V.
Титла: Re: fatal error: time.h: No such file or directory
Публикувано от: jazzman в 17 Януари 2017, 00:52:09
Недуразението идва от тук - 5.0/1023. Ако обърна 5v към mV става 5000. Сори, трябваше да напиша - 0.71v.  Нямам време да замеря волтажа с мултиметъра си, но изхода е следният ( без и със двата диода) :

Код: C
  1. Outside Temperature: 0.72
  2. Outside Temperature: 0.72
  3. Outside Temperature: 0.72
  4. Outside Temperature: 1.68
  5. Outside Temperature: 1.68
  6. Outside Temperature: 1.68
  7.  
  8.