Инфракрасный датчик температуры, проблема
- Войдите на сайт для отправки комментариев
Добрый день, приобрел Grove Infrared Temperature Sensor.
Залил на ардуино демо код. В SerialPort должна писаться температура. А выводится вот такой текст в какой то странной кодировке: "?@¬ê?33£?ú~*?9ý?°?ìQ8?72¢@\@h@Zd@ÙÎw@{^@ÕxA@^º!@¤pý?°?ìQ8?-0ý?°?ìQ8?719w@{^@ÕxA@^º!@¤pý?°?ìQ8?{^@ÕxA@^º!@¤pý?°?ìQ8?"
Поидее все переменные типа float, попытался вывести переменную отдельно закоментив остальные принтфы. Вот это Serial.println(final_temp,2); пишет в порт такие строки: "9ý?°?ìQ8?00
1ý?°?ìQ8?22
1ý?°?ìQ8?22
1ý?°?ìQ8?22
1ý?°?ìQ8?22
1ý?°?ìQ8?22
1ý?°?ìQ8?22
9ý?°?ìQ8?00
9ý?°?ìQ8?00"
Вобщем сижу не могу понять что это? Другие программы работают нормально и пишут в порт то что нужно. Может кто-нибудь сталкивался? Уже 2 дня бьюсь, не могу понять.
Вот код программы:
#include <math.h> const int temp_analog_in = A0; // Analog input pin connect to temperature sensor SUR pin const int objt_analog_in = A1; // Analog input pin connect to temperature sensor OBJ pin float temp_calibration=0; //this parameter was used to calibrate the temperature float temperature_range=10; //we make a map of temperature-voltage according to sensor datasheet. 10 is the temperature step when sensor and //object distance is 9CM. float offset_vol=0.014; //this parameter was used to set the mid level voltage,when put the sensor in normal environment after 10 min, //the sensor output 0.For example,the surrounding temperature is 29℃but the result is 27℃ via the sensor, //you should set the reerence to 0.520 or more,according to your sensor to change. //the unit is V float tempValue = 0; float objtValue= 0; float current_temp=0; float temp=0; float temp1=0; float temp2=0; unsigned int temp3=0; const float reference_vol=0.500; float R=0; float voltage=0; long res[100]={ 318300,302903,288329,274533,261471,249100,237381,226276,215750,205768, 196300,187316,178788,170691,163002,155700,148766,142183,135936,130012, 124400,119038,113928,109059,104420,100000,95788,91775,87950,84305, 80830,77517,74357,71342,68466,65720,63098,60595,58202,55916, 53730,51645,49652,47746,45924,44180,42511,40912,39380,37910, 36500,35155,33866,32631,31446,30311,29222,28177,27175,26213, 25290,24403,23554,22738,21955,21202,20479,19783,19115,18472, 17260,16688,16138,15608,15098,14608,14135,13680,13242,12819, 12412,12020,11642,11278,10926,10587,10260,9945,9641,9347, 9063,8789,8525,8270,8023,7785,7555,7333,7118,6911}; float obj [13][12]={ /*0*/ { 0,-0.274,-0.58,-0.922,-1.301,-1.721,-2.183,-2.691,-3.247,-3.854,-4.516,-5.236}, // /*1*/ { 0.271,0,-0.303,-0.642,-1.018,-1.434,-1.894,-2.398,-2.951,-3.556,-4.215,-4.931}, //→surrounding temperature,from -10,0,10,...100 /*2*/ { 0.567,0.3,0,-0.335,-0.708,-1.121,-1.577,-2.078,-2.628,-3.229,-3.884,-4.597}, //↓object temperature,from -10,0,10,...110 /*3*/ { 0.891,0.628,0.331,0,-0.369,-0.778,-1.23,-1.728,-2.274,-2.871,-3.523,-4.232}, /*4*/ { 1.244,0.985,0.692,0.365,0,-0.405,-0.853,-1.347,-1.889,-2.482,-3.13,-3.835}, /*5*/ { 1.628,1.372,1.084,0.761,0.401,0,-0.444,-0.933,-1.47,-2.059,-2.702,-3.403}, /*6*/ { 2.043,1.792,1.509,1.191,0.835,0.439,0,-0.484,-1.017,-1.601,-2.24,-2.936}, /*7*/ { 2.491,2.246,1.968,1.655,1.304,0.913,0.479,0,-0.528,-1.107,-1.74,-2.431}, /*8*/ { 2.975,2.735,2.462,2.155,1.809,1.424,0.996,0.522,0,-0.573,-1.201,-1.887}, /*9*/ { 3.495,3.261,2.994,2.692,2.353,1.974,1.552,1.084,0.568,0,-0.622,-1.301}, /*10*/ { 4.053,3.825,3.565,3.27,2.937,2.564,2.148,1.687,1.177,0.616,0,-0.673}, /*11*/ { 4.651,4.43,4.177,3.888,3.562,3.196,2.787,2.332,1.829,1.275,0.666,0}, /*12*/ { 5.29,5.076,4.83,4.549,4.231,3.872,3.47,3.023,2.527,1.98,1.379,0.72} }; float binsearch(long x)// this function used for measure the surrounding temperature { int low,mid,high; low=0; //mid=0; high=100; while (low<=high) { mid=(low+high)/2; if(x<res[mid]) low= mid+1; else//(x>res[mid]) high=mid-1; } return mid; } float arraysearch(float x,float y)//x is the surrounding temperature,y is the object temperature { int i=0; float tem_coefficient=100; i=(x/10)+1; voltage=(float)y/tem_coefficient; for(temp3=0;temp3<13;temp3++) { if((voltage>obj[temp3][i])&&(voltage<obj[temp3+1][i])) { return temp3; } } } float temp_measure() { unsigned char i=0; float current_temp1=0; int signal=0; tempValue=0; for(i=0;i<10;i++) // { tempValue+= analogRead(temp_analog_in); delay(10); } tempValue=tempValue/10; temp = tempValue*1.1/1023; R=2000000*temp/(2.50-temp); signal=binsearch(R); current_temp=signal-1+temp_calibration+(res[signal-1]-R)/(res[signal-1]-res[signal]); Serial.print("Surrounding temperature:"); Serial.print(current_temp); return current_temp; } float objt_measure() { unsigned char i=0; unsigned char j=0; float sur_temp=0; unsigned int array_temp=0; float temp1,temp2; float final_temp=0; objtValue=0; for(i=0;i<10;i++) { objtValue+= analogRead(objt_analog_in); delay(10); } objtValue=objtValue/10; temp1=objtValue*1.1/1023; sur_temp=temp1-(reference_vol+offset_vol); Serial.print("Sensor voltage:"); Serial.print(sur_temp,3); Serial.print("V"); array_temp=arraysearch(current_temp,sur_temp*1000); temp2=current_temp; temp1=(temperature_range*voltage)/(obj[array_temp+1][(int)(temp2/10)+1]-obj[array_temp][(int)(temp2/10)+1]); final_temp=temp2+temp1; if((final_temp>100)||(final_temp<=-10)) { Serial.println ("out of range!"); } else { Serial.print(" object temperature:"); Serial.println((float)final_temp,2); } } void setup() { Serial.begin(9600); // initialize serial communications at 9600 bps: analogReference(INTERNAL);//set the refenrence voltage 1.1V,the distinguishability can up to 1mV. } void loop() { temp_measure(); objt_measure(); }
Сделайте немного иначе - закомментируйте все выводы в Serial, кроме какого-нибудь символьного вывода (ну, например, Serial.print("Sensor voltage:"); ). Посмотрите, будет ли ваша терминальная программа получать строку без искажений - а то есть подозрение, что у вас с настройками UART что-то не то...
Кстати: а камень какой? Сколько в нем оперативки? А то может быть вы своим массивом float 12*13 все что можно и нельзя отъели.
Вот что выводит Serial.print("Sensor voltage:"); - ÕxA@^º!@¤pý?°?ìQ8?
Если бы с UART было что-то не то, другие прошивки ведь тоже не правильно бы выводили? А так другие выводят что нужно, только эта прошивка выводит каракули
Контроллер - ATmega168
Контроллер - ATmega168
Есть мнение, что у ATMega168 на борту 1024 байт оперативной памяти.
long res[100]: 100*4=400 байт под массив res
float obj [13][12]: 13*12*4=624 байта под массив obj
уже занято ровно 1024 байта.
а еще необходимо разместить буфер UART (128 байт, если не ошибаюсь), программный стек (зависит от глубины вызовов функций, но никак не меньше десятка байт). Ну и по мелочи - все оставшиеся переменные.
Итог: ваш камень не годится для данного алгоритма.
Что делать? Либо камень менять, либо алгоритм. Поэтому у вас два пути (по крайней мере):
a) перейти на ATMega328 (1280, 2560)
b) перевести ваши массивы из RAM во flash-память, объявив их константами. Судя по беглому просмотру кодов, в ходе программы они никак не меняются и перенесут подобное надругательство над собой довольно терпимо.
Попробовал тупо закоментить в первом массиве 80 эелементов оставив 20, и во втором закоментил сначала 7 строк, потом вообще 11 строк оставив массив [2][12]. Выводится всеравно мусор вместо любого текста в любом месте программы.
Тоесть поидее оперативки полюбому должно было хватить, хоть программа и неправильно считала бы, но текст писать в порт должна была бы без мусора..
Чуть позже попробую все же объявить константами массивы, посмотрим что выйдет.
Сделал массивы константой, теперь числовые переменные пишутся в порт как числа, но все же строки пишутся закорючками
вот так выглядит когда все print'ы раскоменчены: 2265®*0030©%M!2265
вот так выглядит строка если выводить только числовые переменные: 22 850 01622 85
Serial.print(current_temp); так : 22 40
Serial.print(sur_temp,3); так: 0140
Serial.println(final_temp,2); выводит так : 23 04
притом изменяется в зависимости от температуры того, на что направлен сенсор только sur_temp эта переменная, остальные каким то рандомом выводятся и совершенно не зависят от того куда направлен сенсор...