[image]

Микроконтроллеры AVR - применение и Краткий Курс - часть 10

 
1 32 33 34 35 36 37 38
KZ Xan #27.04.2013 10:47  @Non-conformist#27.04.2013 10:44
+
-
edit
 

Xan

координатор

Non-conformist> Форум у одного меня глючит?

У меня тоже.
   10.010.0
UA Non-conformist #27.04.2013 17:46  @Xan#27.04.2013 10:47
+
-
edit
 

Non-conformist

аксакал

Освободился от сельхозработ...

***
Большое спасибо всем за содействие! Похоже, объединёнными усилиями проект продвинут на следующую ступеньку по направлению к сияющим высотам опупеоза. АЦП нормально ходит за крутёлкой, всё отсылается и принимается. Лог в папке.

Следующий этап - на выбор: либо писАть лог в память, и уже из памяти отсылать его на комп; либо подключать тензомост и заниматься метрологией. Какие будут предложения?
   
UA Non-conformist #27.04.2013 22:16  @Non-conformist#27.04.2013 17:46
+
-
edit
 

Non-conformist

аксакал

У меня очень умный вопрос по АЦП созрел: а как он определяет, что, например 4,183 В - это именно 4,183 Алессандро Вольта, а не каких-то левых 4,183 Попугая?

Или вы ему (АЦП) в программе указали, что типа максимальное напряжение, которое может на ADC0 поступить - это 5,000 В?
   
RU GOGI #28.04.2013 07:41  @Non-conformist#27.04.2013 22:16
+
-
edit
 
Non-conformist> Или вы ему (АЦП) в программе указали, что типа максимальное напряжение, которое может на ADC0 поступить - это 5,000 В?
Разумеется. По другому никак.
   20.020.0
KZ Xan #28.04.2013 10:26  @Non-conformist#27.04.2013 22:16
+
-
edit
 

Xan

координатор

Non-conformist> Или вы ему (АЦП) в программе указали

В test.c есть строчка
Voltage = Fix_Mul(Voltage, 0x2008); // Умножаем на константу = 0.50049

Если хочешь поменять константу, то она считается так:

0.50049 * 214 = 8200 = 0x2008

Если б опорное у тебя было бы 3 вольта, то константу можно было бы сделать

0.3 * 1.001 * 16384 = 4920.1152

Voltage = Fix_Mul(Voltage, 4920);

1.001 — это чтобы при всех единицах с АЦП показывало не 2.997, а 3.000.
   10.010.0
UA Non-conformist #28.04.2013 13:48  @Xan#28.04.2013 10:26
+
-
edit
 

Non-conformist

аксакал

Non-conformist>> Или вы ему (АЦП) в программе указали
Xan> В test.c есть строчка
Xan> Voltage = Fix_Mul(Voltage, 0x2008); // Умножаем на константу = 0.50049
1. Откуда взялось значение 0.50049?
2. Что за (переменная?) Fix_Mul
3. Или наоборот, переменная - это Voltage, которой присваивается то, что стоит справа от "="?
4. Что за форма записи 0х2008 - что такое "х"?
5. Как вообще по-человечески читается эта строчка? "Взять константу ФиксМул, умножить ея на содержимое входного регистра (буфера?) АЦП, и присвоить получившееся значение переменной Вольтаж? Хе-хе...


Xan> Если хочешь поменять константу, то она считается так:
Xan> 0.50049 * 214 = 8200 = 0x2008
Откуда считается? От глагола "считывать" или "посчитать"?
Опять - откуда 0.50049 ?

Xan> Если б опорное у тебя было бы 3 вольта, то константу можно было бы сделать
Xan> 0.3 * 1.001 * 16384 = 4920.1152
Почему если опорное 3В, то в расчётах берётся одна десятая от него?
Как получилось значение 1.001? Подбором, или как-то иначе?

Вообще, жестковато пока...
   
KZ Xan #28.04.2013 17:14  @Non-conformist#28.04.2013 13:48
+
-
edit
 

Xan

координатор

Non-conformist>

В файле Test:

Где-то из АЦП берётся сумма 64 отсчётов и засылается в Вольтадж:

Voltage = ADC_Result; // Берём результат при запрещённых прерываниях

И значение печатается как хекс:

Send_Hex2(Voltage); // Посылаем его как hex
Send_Byte(' ');

Существуют числа с фиксированное точкой (в Си их нет), в отличие от "с плавающей" (которые в Си есть).
Они хороши тем, что у них есть дробная часть, но зато нет экспоненты. На отсутствии экспоненты в памяти и в вычислениях экономятся ресурсы.
Единственное что надо сделать, это договориться, какие разряды двоичного числа будет считать целой частью, а какие дробной.
Ну вот я решил для своих чисел считать первый разряд знаковым, второй разряд целой частью, а остальные 14 — дробной.
Тогда некоторые числа будут выглядеть так:
0000000000000000 = 0.0000
0100000000000000 = 1.0000
0010000000000000 = 0.5
0001000000000000 = 0.25
0000100000000000 = 0.125
0111111111111111 = 1.9999 — примерно
1100000000000000 = -1.0000

Числа с фиксированной точкой (на мой взгляд) очень хороши для обработки данных с датчиков (АЦП). Потому что удобно считать, что сигнал с датчика может меняться в пределах 0.0 ... 1.0 (или 0.0000 ... 0.9999).
И его можно умножать или делить на коэффициент не сильно отличающийся от единицы.

Ну вот, чтоб загнать значение с АЦП в диапазон 0.0 ... 0.999, я сдвигаю его на два разряда, тогда максимально возможное значение получается
0011111111110000 = 0.9990

Voltage >>= 2; // Сдвигаем, чтоб получилось в диапазоне 0.0 ... 0.9999
Voltage &= 0X3fff; // На всякий случай гасим 2 старших разряда

В Си числовые константы могут записываться в разных системах. Например, в шестнадцатеричной.
Чтоб компилятор это понял, перед числом пишут префикс "0x", например, 0xFFFF.

Voltage = Fix_Mul(Voltage, 0x2008); // Умножаем на константу = 0.50049

Тут я вначале хотел поставить константу ровно 0.5000, а это

0010000000000000 = 2000 шестнадцатеричное

Кстати, у двоичных префикс "0b"
0b0010000000000000 = 0x2000 = 8192

Так как мне захотелось, чтоб прога могла показать 5.000 вольт, надо, чтоб из значения АЦП = 0x3FF0 = 16368 получалось 0x2000 = 8192
А для этого его надо умножить на 0.50049 (в представлении с фиксированной точкой) = 8200 (в целых числах, которые понимает Си) = 0x2008
   10.010.0
UA Non-conformist #28.04.2013 19:27  @Xan#28.04.2013 17:14
+
-
edit
 

Non-conformist

аксакал

Т.е. сишные вычисления с фиксированной точкой - это чисто твоё изобретение, я правильно понял?

А чем хороша шестнадцатеричная система? Почему в текстах программ очень часто можно видеть числа с префиксом 0х? Это как-то связано с железом восьмибитных МК?
   
UA Non-conformist #28.04.2013 19:34  @Xan#28.04.2013 17:14
+
-
edit
 

Non-conformist

аксакал

Xan> 0010000000000000 = 2000 шестнадцатеричное
Виндовый калк не подтверждает. )) И так, и сяк = никак. ???
   
RU Андрей Суворов #28.04.2013 20:12  @Non-conformist#28.04.2013 19:34
+
-
edit
 

Андрей Суворов

координатор

Xan>> 0010000000000000 = 2000 шестнадцатеричное
Non-conformist> Виндовый калк не подтверждает. )) И так, и сяк = никак. ???

а у меня сошлось. что-то ты не то делаешь.
   7.07.0
RU GOGI #28.04.2013 20:17  @Non-conformist#28.04.2013 19:27
+
-
edit
 
Non-conformist> А чем хороша шестнадцатеричная система?
Алексей, я же тебе пару страниц назад писал.
   20.020.0
KZ Xan #28.04.2013 20:42  @Non-conformist#28.04.2013 19:27
+
-
edit
 

Xan

координатор

Non-conformist> Т.е. сишные вычисления с фиксированной точкой - это чисто твоё изобретение, я правильно понял?

Не, не моё, в очень древних компах было. :)
Но для младших МК хорошо идёт, так как экономит ресурсы.
Поэтому я это себе сделал и пользуюсь.
   10.010.0
UA Non-conformist #28.04.2013 23:50  @Xan#28.04.2013 20:42
+
-
edit
 

Non-conformist

аксакал

А можно ли каким-то образом автоматизировать графическое представление данных в Экселе? Написать некий макрос, чтобы при импорте данных из монитора автоматически чертился красивый график единожды настроенного формата?

Сейчас, например, после импорта данных из Монитора, нужно разделять их на столбцы по пробелу, лишнее удалять, а десятичную точку заменять запятой. В результате чего получается только одна ось - значений напряжения. Оси времени нет. Заменяю её инкрементальным (?) столбцом (+1). И только после этих манипуляций получаю нормальную диаграмму.

В идеале вижу такой процесс: нажимаем на файл спредшита, открывается форма (типа SRM, только попроще). Копипастим туда ворох данных из памяти - и сразу получаем график, без лишних телодвижений. ???
   
UA Non-conformist #29.04.2013 12:18  @Non-conformist#28.04.2013 23:50
+
-
edit
 

Non-conformist

аксакал

Большое спасибо за высказанные соображения!

***
Подключил тензомост к АЦП. Кривую медленного нагружения рамки двумями руками прилагаю сюда. Файл с данными в общей папке.

По наводке:
1. Конструкцию не заземлял
2. Обнаружен косяк с раздельными землями (аналоговой и цифровой) - они должны были встречаться на минусовой клемме батареи питания, но по факту встречаются где-то раньше. Видимо, одна из микрозаклёпок, сшивающих слои, оказалась лишней.
   
KZ Xan #29.04.2013 12:35  @Non-conformist#28.04.2013 23:50
+
-
edit
 

Xan

координатор

Non-conformist> Сейчас, например, после импорта данных из Монитора, нужно разделять их на столбцы по пробелу, лишнее удалять, а десятичную точку заменять запятой.

В Test надо выкинуть строчки

Send_Hex2(Voltage); // Посылаем его как hex
Send_Byte(' ');

и

Send_Byte('.'); // вставив для красоты десятичную точку.

Получится один столбец с целыми числами.

В экселе тычешь в заголовок столбца, чтоб он весь посинел, вниз до бесконечности.
Потом в меню графиков выбираешь вид графика.

А если теперь из текстового файла скопировать новый столбец поверх старого, то и график перерисуется.
(Вначале можно стереть старое содержимое столбца.)
   10.010.0
UA Non-conformist #18.05.2013 13:56  @Non-conformist#29.04.2013 12:18
+
-
edit
 

Non-conformist

аксакал

> ... Фраза до фразы sum показывает какой тип данных будет возвращен функцией. Необходимо понимать, функция возвратит только одно значение (одно число). Необходимо также понимать, что функция не может возвращать одновременно больше одного значения. Либо одно значение одного из типов, либо ничего (пустое), т.е. void.

> Фразы в скобках после sum показывают какого типа данные будут переданы в функцию. Здесь ограничений нет, в функцию можно передавать много значений разных типов.

> Как бы мы не назвали функцию (хоть zadnica) мы обязательно должны сказать, что передаем в функцию и что по результатам вычислений функция возвращает, ну например, void zadnica (long int her).

Живо, образно. Запоминающе.
   

Xan

координатор

Скопирую ещё и сюда, вдруг кто-нибудь что-то умное скажет.

Клиент (в другом городе) жалуется, что моя железка и моя прога у него дают "ошибки связи".
Связь через длинный кабель (около 1 км) витой пары по RS485.
Железная дорога.
Таких штук двадцать успешно работает годами, никто не жаловался.
А тут у клиента попёрло.
Ошибки такие: небольшое число байтов (порядка процента) принимается с ошибками frame и parity (одновременно или нет - не знаю).
Инфа прёт пакетами по 10 байтов с частотой 1000 пакетов в секунду.
Точнее так: 10 байтов по 11 битов + 5 битов паузы = 115200 / 115 = 1001.74 в секунду.
Ошибки, похоже, любят случаться с последними байтами. Но это не наверняка.

Юзарь катил бочку на плохие платы.
Что вот они подключают старую плату, она работает, подключают новую - не.
Платы скатались ко мне домой и обратно к юзарю.
Как обычно бывает у погромистов — "у меня на столе всё работает!"
И стрелка осциллографа зелёного цвета!!!
У юзаря — то работает, то нет.

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

По логике получается вывод, что компорты херовые, один и тот же ХОРОШИЙ сигнал они то правильно принимают, то с ошибками.

Ну, юзарь крут, паре плат он в процессе экспериментов сжёг порты и прислал на ремонт.
Перепаял микрухи, включил для проверки — ошибки прут!
Приладил опять осциллу — сигнал красивый.
Подключил в параллель второй компорт — ошибки пропали.
Но тут уже я начал проги дёргать-перезапускать и получил то же, что и у юзаря. То работает, то нет в любых комбинациях.

И вот случилась у меня задумчивость на вечную тему — кто виноват и что делать?
ПАМАГИТЯ!!!!!

> электропитание как по мне

Минимум на трёх разных компах.
В том числе и в стерильный условиях.

> А что за железки (платы)? 485-232 или что-то более высокого уровня?

Плата, которая посылает - Pic16F877A + спецмикруха ADM2483BRWZ.

Приёмники:
MOXA PCI 2-канальная без гальванической развязки, у меня в компе для возни с такими платами.
MOXA PCI в клиентском компе.
Самоделка RS485 -> USB с ADM2587EBRWZ и FT232RQ, у моего компа.
Такая же самоделка у клиентского компа.
Китайская херня RS485 -> RS232 подключаемая у клиента в настоящий компорт.
Коробочка ICPCON у клиента.
И ещё что-то у клиента, может быть и не одно.

Дома через моксу и самоделку показываются разные скорости ошибок. То есть, компорты глючат независимо.

В общем думаю, что если ничего не придумаю, то увеличу интервал между пакетами с 5 до 11 битовых интервала. Чтоб пауза была длинная.

Есть подозрение, что в древних платах байты посылались неравномерно, или плотно друг к другу, или с большими паузами. Но со средней скоростью 10000.

Ещё был у меня глюк в другой железке, когда между парой байт была пауза в половину битового интервала. Там иногда тоже пёрли ошибки, лечилось передёргиванием чего-нибудь - проги или железа.

> А бьётся-то в каком участке? удалёнка-485, или на 232-комп на локальной железке?

Лёжа дома на столе (даже не в поле) через любую железку:
RS485 -> USB(компьютер)
RS485 -> PCI(компьютер)
RS485 -> RS232(компьютер)

Данные = константа, так что осциллой прекрасно всё видно, и уровни, и времена.
Ползая на пузе вдоль пакета разглядывал всё.
Сигнал хороший.

Ну и если комп через одну дырку принимает правильно, а через другую с ошибками, это кто виноват?
Получается, что надо показывать пальцем на винду.
Это как-то совсем странно.
   10.010.0
RU Бывший генералиссимус #07.10.2013 10:21  @Xan#07.10.2013 09:54
+
-
edit
 
Xan> Есть подозрение, что в древних платах байты посылались неравномерно, или плотно друг к другу, или с большими паузами. Но со средней скоростью 10000.
USB конвертеры этим грешат, да. Но шлёт же не USB конвертер? Там же контроллер на передающей стороне, где всё железно?

Xan> Ну и если комп через одну дырку принимает правильно, а через другую с ошибками, это кто виноват?

Прерывания.

Xan> Получается, что надо показывать пальцем на винду.
Xan> Это как-то совсем странно.

Прерывания.
   10.010.0
KZ Xan #07.10.2013 11:45  @Бывший генералиссимус#07.10.2013 10:21
+
-
edit
 

Xan

координатор

Б.г.> USB конвертеры этим грешат, да. Но шлёт же не USB конвертер? Там же контроллер на передающей стороне, где всё железно?

МК выдаёт красивый сигнал.
Это видно и на осцилле, и по тому, что соседний компорт принимает правильно.

Б.г.> Прерывания.

Как?
Там, например, нет ошибок overflow, только чётность и кадр.
И почему от запуска к запуску то есть, то нет?

Ну и через 3 совершенно разных входа: USB, PCI, Comport.
   10.010.0
RU Бывший генералиссимус #07.10.2013 12:17  @Xan#07.10.2013 11:45
+
-
edit
 
Б.г.>> Прерывания.
Xan> Как?

Недостаточно информации...

Xan> Там, например, нет ошибок overflow, только чётность и кадр.
Вот это противоречит моей теории, да.
Xan> И почему от запуска к запуску то есть, то нет?
А вот это железный признак, что виноваты прерывания в винде...
Xan> Ну и через 3 совершенно разных входа: USB, PCI, Comport.

Может, там больше одной причины возникновения ошибок.
   10.010.0

Semenov

втянувшийся
Xan> ПАМАГИТЯ!!!!!
1) надо проверить в чем причина ошибки - т.е. при ошибках читать сведения о них, если в ПК это не возможно то параллельно COM ПК подключить uart pic - и им контролировать поступающий сигнал.
2) снизить скорость передачи.
   29.0.1547.7629.0.1547.76
Xan, ты порт полностью перед началом сеанса конфигурируешь, не допускаешь значений "по умолчанию"?
   24.024.0

Xan

координатор

GOGI> Xan, ты порт полностью перед началом сеанса конфигурируешь, не допускаешь значений "по умолчанию"?

code text
  1. BOOL    OpenCommPort(long CommNum, long BaudRate, char Parity)
  2. {
  3. CloseCommPort();
  4. CommOpenFlag = 0;
  5. sprintf(CommPortMes, "----");
  6. sprintf(CommResultMes, "----");
  7. sprintf(CommStatusMes, "----");
  8. if (CommNum < 1 || CommNum > 255)       return(FALSE);
  9.  
  10. sprintf(CommPortMes, "Com%u", CommNum);
  11. hCom = CreateFile(CommPortMes,          // pointer to name of the file
  12.     GENERIC_READ | GENERIC_WRITE,       // access (read-write) mode
  13.     0,                                  // share mode (exclusive access)
  14.     NULL,                               // pointer to security attributes (no)
  15.     OPEN_EXISTING,                      // how to create (must use OPEN_EXISTING)
  16.     0,                                  // file attributes (not overlapped I/O)
  17.     NULL                                // hTemplate must be NULL for comm devices
  18.     );
  19.  
  20. if (hCom == INVALID_HANDLE_VALUE)
  21.     {
  22.     dwError = GetLastError();
  23.     sprintf(CommResultMes, "Cannot open");
  24.     if (dwError == 2)   sprintf(CommResultMes, "Not exists");
  25.     if (dwError == 5)   sprintf(CommResultMes, "Port busy");
  26.     return(dwError);
  27.     }
  28.  
  29. sprintf(CommResultMes, "Ok");
  30. CommPortNum = CommNum;
  31.  
  32. fResult = GetCommState(hCom, &dcb);
  33.  
  34. dcb.BaudRate = BaudRate;
  35. dcb.ByteSize = 8;
  36. if (Parity == 'o')  dcb.Parity = ODDPARITY;
  37. if (Parity == 'e')  dcb.Parity = EVENPARITY;
  38. if (Parity == 'n')  dcb.Parity = NOPARITY;
  39. dcb.StopBits = ONESTOPBIT;
  40.  
  41. dcb.fBinary =           True;                   // binary mode, no EOF check
  42. dcb.fParity =           True;                   // enable parity checking
  43. dcb.fOutxCtsFlow =      False;                  // CTS output flow control
  44. dcb.fOutxDsrFlow =      False;                  // DSR output flow control
  45. dcb.fDtrControl =       DTR_CONTROL_DISABLE;    // DTR flow control type
  46. dcb.fDsrSensitivity =   False;                  // DSR sensitivity
  47.  
  48. dcb.fTXContinueOnXoff = True;                   // XOFF continues Tx
  49. dcb.fOutX =             False;                  // XON/XOFF out flow control
  50. dcb.fInX =              False;                  // XON/XOFF in flow control
  51. dcb.fErrorChar =        False;                  // enable error replacement
  52. dcb.fNull =             False;                  // enable null stripping
  53. dcb.fRtsControl =       RTS_CONTROL_DISABLE;    // RTS flow control
  54. dcb.fAbortOnError =     False;                  // abort reads/writes on
  55.  
  56. fResult = SetCommState(hCom, &dcb);
  57.  
  58. if (!fResult)
  59.     {
  60.     dwError = GetLastError();
  61.     sprintf(CommStatusMes, "StateError");
  62.     return(FALSE);
  63.     }
  64.   else
  65.     {
  66.     dwError = GetLastError();
  67.     sprintf(CommStatusMes, "Ok");
  68.     }
  69.  
  70. CommTimeOuts[0] = MAXDWORD;         // ReadIntervalTimeout
  71. CommTimeOuts[1] = 0;                // ReadTotalTimeoutMultiplier
  72. CommTimeOuts[2] = 0;                // ReadTotalTimeoutConstant
  73. CommTimeOuts[3] = 1;                // WriteTotalTimeoutMultiplier
  74. CommTimeOuts[4] = 1;                // WriteTotalTimeoutConstant
  75. fResult = SetCommTimeouts(hCom, (LPCOMMTIMEOUTS) CommTimeOuts);
  76.  
  77. if (!fResult)
  78.     {
  79.     dwError = GetLastError();
  80.     sprintf(CommStatusMes, "TimeOutError %x", dwError);
  81.     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
  82.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), CommStatusMes, 390, NULL);
  83.     sprintf(CommStatusMes, "TimeOutError %x", dwError);
  84.     return(FALSE);
  85.     }
  86.   else
  87.     {
  88.     sprintf(CommStatusMes, "Ok %X %x %x %x %x", CommTimeOuts[0], CommTimeOuts[1],
  89.     CommTimeOuts[2], CommTimeOuts[3], CommTimeOuts[4]);
  90.     }
  91.  
  92. ClearCommError(hCom, &Errors, NULL);
  93.  
  94. CommOpenFlag = 1;
  95. CreateMyThread();
  96. if (MyThreadFlag != 1)
  97.     {
  98.     CloseCommPort();
  99.     return(FALSE);
  100.     }
  101. return(TRUE);
  102. }


Каждый тип ошибки увеличивает соответствующий счётчик, так что ошибки незамеченными не проходят.
Но не детально по каждому байту а вообще с момента открытия компорта.
   10.010.0

Xan

координатор

Semenov> 1) надо проверить в чем причина ошибки - т.е. при ошибках читать сведения о них, если в ПК это не возможно то параллельно COM ПК подключить uart pic - и им контролировать поступающий сигнал.

Так уже сигнал идёт сразу в два порта. Не считая осциллографа.
И один принимает правильно, а другой с ошибками.
А потом наоборот — Шарик Шарика ... ето самое! :)

Semenov> 2) снизить скорость передачи.

Нельзя.
   10.010.0
Раз уж два порта на одном компьютере сразу пробуешь, попробуй из одного в другой большие объемы передавать туда и обратно.
   24.024.0
1 32 33 34 35 36 37 38

в начало страницы | новое
 
Поиск
Поддержка
Поддержи форум!
ЯндексЯндекс. ДеньгиХочу такую же кнопку
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru