Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Проблема с adc. Help


Проблема с adc. Help

Сообщений 1 страница 30 из 55

1

Я ещё совсем зеленый в программировании, поэтому прошу помощи, месяц бьюсь с этой проблемой и безуспешно.
Проблема такая: (опишу в грубой форме)
Тинька 44, есть 3 кнопки подключены к adc входу тиньки. При нажатии кнопки 1, происходит измерение  adc и если значение верное то порт1 из уровня Z переходит в 0. Тот же принцип и с другими кнопками, то есть кнопка 2 управляет портом 2, а кнопка 3 управляет портом 3. Этот код я написал. Но возникла проблема, при нажатии кнопки1 срабатывает порт 3 (вместо порта1) и не могу понять почему так? Один товарищ говорит что это из-за "дребезга" кнопок. Прописал задержку (waitms...) но не помогло. Тогда посоветовали прописать код двойного измерения на кнопку, так сказать с сравнением первого и второго значения, снятые с кнопки, НО я так и не понял как это сделать. (Тот кто советовал пишет в Си и в баскоме не понимает)
Подскажите как примерно  должен выглядеть код двойного измерения с сравнением? Или ссылку на пример? Или может проблема в другом? Примного благодарен.

0

2

Можно Ваш код посмотреть?

0

3

Полноценный код нет возможности отправить, пишу с калькулятора, но приблизительно у меня написано следующее (расписывать подробности как portb.0, portd.1 и прочее, не стал, чтоб не заморачиваться)

Программа примерно такая: (грубо напишу)

Код:
config port1 input
config port2 input
config port3 input
Это настройка портов в высокий уровень z

Dim A as string
Это объявление некой переменной

Config adc бла бла бла настройка ацп 

Start adc 
Включаем ацп 

Do (начало программы)

 A = getadc

if A > 200 and  A < 300 then 
Port1 = output
Also 
Port1 = input
End if

if A > 400 and  A < 500 then 
Port2 = output
Also 
Port2 = input
End if

if A > 600 and  A < 700 then 
Port3 = output
Also 
Port3 = input
End if

Loop
End

0

4

Вы переключаете пины на вход или выход, это неправильно.

Изначально нужно сконфигурировать их на выход

config porta.1 = output
config porta.2 = output
config porta.3 = output

, а затем, в зависимости от условий, устанавливать их в состояние лог 0 или 1

Set porta.1 или potra.1 = 1

И

Reset porta.1 или potra.1 = 0

0

5

Спасибо, я попробую )))

0

6

По поводу непосредственно, АЦП, чтобы получить точное значение, неплохо бы делать серию измерений, например, 10...100...1000, усреднять их значения и от него уже плясать.

Делаю, как правило, в массиве, суммирую в цикле.

Маленькая хитрость - в цикле проверять значение последнего элемента массива, и, если оно ноль, каждому элементу массива присваивать текущее значение ацп.
В этом случае, среднее арифметическое не будет расти от нуля, а сразу примет некоторое значение ацп, и от него поползёт вниз или вверх и устаканится.

Отредактировано demonizer (2017-01-17 12:33:42)

0

7

Массив для усреднения - это прошлый век, я так тоже раньше морочился, тратил на это время процессора и тучу памяти, в итоге всё делается очень просто: накапливаем/суммируем результат АЦП в 16-бит переменной "word" и делим общее количество измерений на результат. Соответственно: максимальное количество измерений может быть 63 (6-бит (16-10), этого обычно достаточно, особенное, если измерения проводить не на макс частоте АЦП (которое кстати добавляет кучу шума/погрешности/грубости), если этого недостаточно, разрядность переменной можно увеличить.
Достоинства: не требует много памяти МК (только переменные), данные статичны, т.е. в отличии от массива, они постоянно не меняются по всей длине, так же не тратиться кучу времени процессора на обработку массива (всё линейно по производительности, что регламентирует стабильность), целочисленность.

зы: деление можно делать обычным сдвигом на 6 бит.  :flirt:

Отредактировано RDW (2017-01-17 13:08:23)

0

8

RDW

ТС нужно понимать сам принцип, примеров реализации масса, можно использовать всего одну переменную типа word и без суммирований, по условию увеличивать значение, если она меньше значения ацп и уменьшать, если больше. и ничего не нужно суммировать и делить

0

9

Что-то до меня не доходит как правильно написать код. Внёс изменения по советам, но проблема осталась. Повторюсь, на ацп повешаны 3 кнопки (у каждой свой резистор), эти кнопки управляют 3 портами, на которые повешаны светодиоды (катодом на порт). При нажатии на определенную кнопку срабатывает порт который  запрограммирован на эту кнопку и ложно срабатывает другой порт. Расчеты измерений точные, считал по формуле adc = (Vin * 1024)/ Vref. Знаю что управлять светодиодами можно и по-другому, но мне нужно именно с помощью ацп. Подскажите ещё раз, что не так? Код прикрепляю

Код:
  $regfile = "attiny44.dat" 
$crystal = 8000000 
 
 
 
Config Adc = Single , Prescaler = 64 , Reference = Avcc 
 
 
Dim A As Integer 
 
Config Portb.0 = Output 
Config Portb.2 = Output 
Config Porta.7 = Output 

 
Start Adc 
 
Do 
 
A = Getadc(3) 
Waitms 50 
 
If A >= 60 And A <= 90 Then 
Reset Portb.0 
Else 
Set Portb.0 
End If 
 
 
If A >= 200 And A <= 250 Then 
Reset Portb.2 
Else 
Set Portb.2 
End If 
 
If A >= 120 And A <= 160 Then 
Reset Porta.7  
Else 
Set Porta.7 
End If 
 

Loop 
End

спасибо)))

Отредактировано Octav (2017-01-20 09:57:40)

0

10

1. Чтобы АЦП мерил точно, надо хорошие питание МК или вешать внешнее на AREF (если такое имеется, в тини он вроде есть).
2. Если не хочется мороки с стабильностью АЦП, то проще сделать алгоритм с некими допусками, например:

- приходит измерение с АЦП;
- производим сравнение с N числом соответствующее резистору/кнопке, причем сравнивать допуск +/- значение (скажем 10).
- дальше уже можно назначать этим значениям/кнопкам/резисторам действия на порты.

Но чтобы этот алгоритм работал, надо для начала настроить, узнать какое значение приходит на АЦП при измерении резистора, для этого нужно сделать временный вывод значений, относительно которых будем уже плясать (через порт UART или индикаторы).

0

11

Aref задействовал, глюк так и не пропал.
Сравнения делал, но тоже безрезультатно :(

0

12

http://sf.uploads.ru/t/Q0C5P.jpg
Схема примерно такая, номинал резисторов в Омах,  резистор делителя ацп 1кОм, (резистор Reset 10кОм есть), светодиоды тоже с резисторами, чтоб порты не позжечь. все расчеты верны. Кнопки менял, фильтр собирал (чтоб дребезг исключить) ничего не помогает, не могу понять, что ещё я упустил

0

13

Octav
Порты,к которым подключены светодиоды сконфигурированы на вход,а работают они на выход.

0

14

У вас схема из резисторов не совсем правильная, нужно собрать обычный делитель и чтобы только один резистор всегда менялся кнопками (под каждую кнопку свой резистор, получится много параллельно включенных резисторов).
Резисторы должны все быть разного номинала, самое простое, кратность двум (параллельное подключение одного и того же номинала).
Два резистора по 82 Ома - всегда ровны, т.е. две кнопки будут выдавать одинаковое значение.

Отредактировано RDW (2017-01-19 14:43:30)

0

15

Почему пины сконфигурированы на вход, а не на выход?

demonizer написал(а):

Изначально нужно сконфигурировать их на выход
config porta.1 = output
config porta.2 = output
config porta.3 = output

0

16

RDW написал(а):

Два резистора по 82 Ома - всегда ровны, т.е. две кнопки будут выдавать одинаковое значение.

Боюсь, средняя кнопка "даст" 164 Ома, а не 82

0

17

На выходы пины сконфигурированы, это я случайно перепутал, когда код набивал сюда

0

18

В общем это дребезг кнопки, фильтр его не устраняет, замена кнопки бесполезна ибо другая окажется такая же, как можно  программно устранить дребезг? Использовать таймер и прерывания? Но тогда как это написать, я совсем не понимаю, знаний не хватает...

0

19

http://s9.uploads.ru/t/rQaOG.png

'-------------  Настройка АЦП  -------------------------------------------------
  Config Adc = Single , Prescaler = 128 , Reference = Avcc
'--------------  Используемые переменные для работы с АЦП  ---------------------
  Dim Готовые_данные_ацп_word(8) As Word

   Готовые_данные_ацп_word(1) = Getadc(0)

0

20

использую кнопки на АЦП несколько лет. никаких усреднений не делаю

Код:
Config Adc = Single , Prescaler = Auto , Reference = Avcc : Start Adc             

Opros_knopok:
   Adc_data = Getadc(7)
   If Adc_data > 100 Then     ' Если что-то нажато
      Waitms 30               ' Защита от помех и дребезга контактов
      Adc_data = Getadc(7)
      If Adc_data > 100 Then  ' Если что-то нажато
         '         Print "ADC=" ; Adc_data
         If Adc_data > 120 And Adc_data < 200 Then Button = 4       ' Кнопка 4
         If Adc_data > 270 And Adc_data < 350 Then Button = 3       ' Кнопка 3
         If Adc_data > 430 And Adc_data < 510 Then Button = 5       ' Кнопка 5
         If Adc_data > 610 And Adc_data < 680 Then Button = 6       ' Кнопка 6
         If Adc_data > 760 And Adc_data < 840 Then Button = 2       ' Кнопка 2

          If Adc_data > 950 Then Button = 1       ' Кнопка 1

         '         Do        ' Ждём, когда отпустят кнопку
         '            Waitms 30
         '            Adc_data = Getadc(7)                            ' Если что-то нажато
         '         Loop Until Adc_data < 50
      End If
   End If
Return

http://sg.uploads.ru/t/9a1Q2.jpg

Отредактировано Александр Д. (2017-01-20 08:52:15)

0

21

или вот, чужая схема, я ставил свой МК и писал под эту схему ПО.

Код:
' Настройка АЦП
Config Adc = Single , Prescaler = Auto , Reference = Avcc : Start Adc


   Temp_w = Getadc(6)         ' Измеряем напряжение в канале 6

   Shift Temp_w , Right , 2   ' делим на 4, чтобы в 1 байт влезло
   '   Print #1 , Temp_w


   Temp = Temp_w


   If Temp < 250 Then         ' Что-то нажато ...
      Tx = 0
      Porta = 0 : Portb = 0

      If Temp < 5 Then
         St_run:
            Tx = 1            ' 1
            Ant_1 = 1
      End If

      If Temp > 29 And Temp < 35 Then
         Tx = 2               ' 2
         Ant_2 = 1
      End If

      If Temp > 62 And Temp < 68 Then
         Tx = 3               ' 3
         Ant_3 = 1
      End If

      If Temp > 90 And Temp < 96 Then
         Tx = 4               ' 4
         Ant_4 = 1
      End If


      If Temp > 123 And Temp < 129 Then
         Tx = 5               ' 5
         Ant_5 = 1
      End If

      If Temp > 157 And Temp < 163 Then
         Tx = 6               ' 6
         Ant_6 = 1
      End If

      If Temp > 183 And Temp < 189 Then
         Tx = 7               ' 7
         Ant_7 = 1
      End If

      If Temp > 215 Then
         Tx = 8               ' 8
         Ant_8 = 1
      End If

http://s7.uploads.ru/t/q4QLy.jpg

0

22

Добавлял ещё одну переменную, но........ смешно уже))))

Код:
.........
Dim A as.....
Dim B as.....
Dim C as....

...........

Do
A = Getadc(3)
Waitms 50
B = Getadc(3)
Waitms 50

If A= B Then
C = 1
Else
C = 0
End If

If A >= 60 And A <= 90 and C = 1Then 
Reset Portb.0 
Else 
Set Portb.0 
End If

.............
.............
.............

Loop
End

0

23

А что ....смешно?
пробуй читать ADC 2 раза с интервалом 10 мкс.

Отредактировано Каримов (2017-01-20 10:43:58)

0

24

Вам бы не программу бросаться сразу писать законченную, а разобраться вначале как всё работает. Вам уже куча народа сделало тучу предложений вариантов (за ВАС и это всё есть в инете), а во до сих пор только смеётесь.

0

25

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

0

26

Странно! ВСЁ работает с одним чтением ADC. Я только что сделал на NANO макет.

Критично время опроса? Сделай опрос ADC 5 раз в цикле с делением на 5 (определишь СРЕДНЕЕ).

A = getadc
B = getadc
C = getadc
D = getadc
E = getadc

ADC_total = A+B+C+D+E
ADC_total = ADC_total/5

0

27

В АВР есть один глюк с АЦП, это когда при включении МК при первом измерении приходит глюк, в зависимости от версии баскома этот баг железа учитывается. Если сильно параноить, то это измерение можно делать разово самому при включении МК.
Но даже если на этом не циклиться, то у вас явно в другом проблема.

1. определите, что кнопки 100% работают как надо (например зажигайте светодиоды);
2. проверьте отдельно правильность работы порта/ввод/вывод;
3. только затем производите соединение кода воедино.

Если у вас совсем не получается и не понимаете что и как делать, то выложите СЮДА исходный ВАШ код, может кто-то захочет в нём разобраться и подскажет/напишет...

зы: а так разговор с ветром, вы выкладываете непонятные куски, что-то там скрывая, когда ценности в этом 0.

0

28

RDW
Присоединяюсь! Встречал такой глюк! Решалось повторным опросом ADC.

Для пробы:
Замкни ПЕРЕМЫЧКОЙ одну из кнопок.
Do
     'читай adc
     'сравни диапазон измерений. Если тот - включи 1-й led
     'жди секунду. выкл 1-й led
     'если не тот - включи 2-й led
     'жди секунду. выкл 2-й
LOOP

Проблема может быть в мембранных кнопках.

Отредактировано Каримов (2017-01-20 13:26:20)

0

29

Каримов написал(а):

мембранных кнопках

Зависит от типа кнопки, если они вообще пластиной на плату замыкают, то там черт знает что может творится.
Я когда переделывал РЖД поезд, там 4-е кнопки вообще были резисторные, токопроводящяя резина - такое Г, жуть. По началу пытался с ними работать, но там вообще засада, разброс сопротивления от силы/формы нажатия - космос, после долгих мучений, всё переделал на обычные кнопки и проблема решилась.
Я по этому и говорю, чтобы топикстартер сделал тест чисто клавы/кнопок.

0

30

Если работать с такими (резина, пленка, и т.п.) кнопками ПРИ большИх сопротивлениях в делителе - Железо работает! Даже без сбоев. ГЛАВНОЕ выбрать ШИРОКИЙ ДИАПАЗОН нажатия кнопки.
Пример: 1-я кнопка при замере = 400, 2-я = 1000, 3-я = 4000 ....
То 1-й диапазон= 50-700, второй = 701-2500 ....
Не желательно оставлять "пустоты" между диапазонами.

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Проблема с adc. Help