ADC работает с потенциометрами, но не с пьезоэлементами.

У меня АЦП на stm32f429 с включенными 3 каналами(запись данных с DMA). Хотя я подозреваю, что этот вопрос может быть не специфичным для STM32, возможно, это общий вопрос АЦП.

«ОТВЕТ»
Я нашел «решение». Пробовал использовать 6 и 7 канал вместо 1 и 2 - проблема исчезла. Судя по всему, каналы 1 и 2 "особые", хотя в даташите я не нашел почему (или пропустил). Может они более требовательны к подводимой мощности, идк. Если есть кто-то, кто может дать какую-то информацию - не стесняйтесь, я приму это как ответ (если он достаточно хорош). Может быть, это специфично для stm32, кто знает...

  • Все 3 канала получают правильное значение преобразования АЦП, если я подключаю их к потенциометру (или напрямую к Vcc (значение 4095) или GND (значение 0))
  • Если я оставлю их плавающими, то все начнет становиться странным - канал 0 имеет значение ~ 400, а каналы 1 и 2 имеют значение 0. Что происходит?
  • И реальная проблема - у меня есть 3 датчика, которые я хочу подключить к АЦП, но почему-то работает только канал 0 АЦП, а каналы 1 и 2 не работают с датчиком (хотя они работали с потенциометрами!)

Что я сделал/заметил:

  1. Это видимо никак не связано с тем, что я использую три датчика - пробовал тестировать по одному - вывод такой, что датчики отлично работают с каналом 0 и вообще не работают на канале 1 и 2, даже при тестировании один за другим, не создавая проблем друг другу.
  2. Это действительно странно - когда я проверяю осциллографом выход моего датчика, он работает нормально без подключения АЦП или с подключенным к нему Каналом 0. Теперь как только я подключаю к нему канал 1 или 2 - осциллограф показывает ноль независимо от того, что я делаю с пьезо.

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

схематический

смоделируйте эту схему - схема, созданная с помощью CircuitLab

На этом скриншоте видно окно отладки в Keil uVision, оно показывает значение 403 на ADC ch 0, даже если к нему ничего не подключено. Я измерил, что это ~ 200-250 мВ. Поскольку канал 0 — единственный, который работает с датчиком, я предполагаю, что на других каналах должно быть то же самое ~ 250 мВ, но это не так.

введите описание изображения здесь

Вот мои конфигурации для stm32f429 с использованием библиотеки HAL. Все каналы должны быть подключены одинаково, но мне интересно, может что-то не так в конфигах...

void MX_ADC1_Init(void)
{

  ADC_ChannelConfTypeDef sConfig;

    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION12b;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = EOC_SEQ_CONV;
  HAL_ADC_Init(&hadc1);

    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);

    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = 2;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);

    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = 3;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);

}

И файл stm32f4xx_hal_msp.c

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hadc->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */

  /* USER CODE END ADC1_MspInit 0 */
    /* Peripheral clock enable */
    __ADC1_CLK_ENABLE();

    /**ADC1 GPIO Configuration    
    PA0/WKUP     ------> ADC1_IN0
    PA1     ------> ADC1_IN1
    PA2     ------> ADC1_IN2 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* Peripheral DMA init*/

    hdma_adc1.Instance = DMA2_Stream0;
    hdma_adc1.Init.Channel = DMA_CHANNEL_0;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;
    hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_DMA_Init(&hdma_adc1);

    __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

  /* Peripheral interrupt init*/
    HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(ADC_IRQn);
  /* USER CODE BEGIN ADC1_MspInit 1 */

  /* USER CODE END ADC1_MspInit 1 */
  }

}

РЕДАКТИРОВАТЬ 1
Я также пытался просто использовать пьезодатчик с резистором 1 МОм - то же самое, как только я подключаю канал 1 или 2 - осциллограф показывает ноль.

РЕДАКТИРОВАТЬ 2
Еще одна странная вещь - я подал звуковой сигнал на контакты ch1 и ch2, и они, кажется, заземлены. О_о

Возможно, вы повредили каналы 1 и 2 чрезмерным напряжением от пьезоэлемента - другими словами, вы не смогли обеспечить защиту от пьезоэлемента, который, вероятно, может генерировать сто вольт с хорошим ударом. Попробуйте переподключить потенциометры и посмотрите, работают ли они на каналах 1 и 2.
Возможно, вы неправильно настроили контакты других каналов как аналоговые входы. Независимо от этого вам также необходимо обратить внимание на тот факт, что входное сопротивление АЦП MCU обычно не так уж велико, и на многих, таких как STM32, становится ниже, чем быстрее вы настраиваете АЦП для преобразования. Вам может понадобиться буферный усилитель, если ваш источник имеет высокое сопротивление.
@ Энди, он же, горшки все еще работают отлично. А пьезо я подключил со стабилитроном 3.3, так что никакие высокие напряжения проходить не должны
Хорошо, тогда попробуйте сместить АЦП с помощью 2 резисторов по 10 кОм на половину полной шкалы, но держите его осторожно, чтобы избежать перенапряжения. Пьезо можно просто поставить параллельно одному из них. Я знаю, что 10 кс слишком мало, но вы не заставите свой АЦП работать должным образом (и по центру) с большими резисторами. Доказательство концептуальной идеи, тогда вам понадобится буферный операционный усилитель и резисторы 1 МОм, чтобы заставить его работать с чувствительностью.
@ChrisStratton, я пытался настроить АЦП на очень медленное преобразование (1 отсчет/480 циклов), но это не влияет на «бездействие» каналов 1 и 2. Я не уверен насчет буферного усилителя, так как видел много проектов, в которых они используют пиццы, напрямую связанные с 1M res(не только stm32, но и avrs и pics)
Последовательный резистор на 1 мОм образует делитель с меньшим входным сопротивлением, ослабляя ваш сигнал.
Новая инфа - выводы для ch1 и ch2 оказались заземлены... это действительно странно, теперь я даже не знаю, почему потенциометры работают.
@ Andyaka Andyaka, кажется, это тоже ничего не делает ... потому что контакт заземлен, поэтому я в основном замыкаю пьезоэлемент на землю. Или оставить плавающим. Если я оставляю его плавающим - осциллограф показывает, что он работает нормально, но АЦП его не регистрирует (поскольку «земля» датчика не заземлена на uC, я полагаю)
Иногда такого рода странности вызваны заземлением тестируемого устройства через систему разработки (например, через USB-разъем) и другое тестовое оборудование. На вашей схеме его нет, поэтому сложно предположить, что именно это может быть.
@SpehroPefhany, он подключен к USB-порту ноутбука, вот и все. Пробовал подключать только с питанием 5В - тоже самое.
Привет, ребята. Я нашел "решение". Пробовал использовать 6 и 7 канал вместо 1 и 2 - проблема исчезла. Судя по всему, каналы 1 и 2 "особые", хотя в даташите я не нашел почему (или пропустил). Может они более требовательны к подводимой мощности, идк. Если есть кто-то, кто может дать какую-то информацию - не стесняйтесь, я приму это как ответ (если он достаточно хорош). Может быть, это специфично для stm32, кто знает...
У меня была/есть похожая проблема на STM32F4Discovery, ADC3 Ch11,12. Пот работает нормально ИК датчик расстояния нет. @ScienceSamovar, а где вы нашли, что каналы 1,2 "особые", это только ваше мнение или вы нашли какой-то документ?
@BenceKaulics, это мое мнение, я ничего не могу найти в таблице данных, но простое переключение каналов, не касаясь чего-либо еще, заставляет меня думать, что ch1 и ch2, вероятно, не совпадают ... может быть, что-то есть в таблице данных, но я не мог не найти его легко. А может я их как-то повредил, хотя в этом случае горшки тоже не работали бы... Это все равно пока загадка... Если найду об этом больше - добавлю в пост.
Существует множество нюансов настройки контактов STM32, которые различаются в зависимости от части и семейства, но включают в себя такие вещи, как питание и синхронизация родительской периферийной шины, настройка альтернативного режима работы, включение/отключение замены контактов и т. д. Вы можете захотеть электрически охарактеризовать поведение выводов путем измерения напряжения при возбуждении различными комбинациями известных резисторов. Вы также можете временно попробовать контакты в качестве цифровых входов — это не то же самое, что аналоговые, но вы можете обнаружить некоторые недочеты (или, что менее вероятно, повреждение).
Я не знаю о контроллерах STM, но я знаю о AVR. В AVR есть что-то под названием «ADCMUX», которое является мультиплексором АЦП. Предположим, что у вас есть 4 канала АЦП. Этот мультиплексор АЦП выберет любой из каналов и обработает его для вывода. Если вы хотите обработать другой канал, вы должны дать соответствующее значение в регистре ADCMUX, чтобы выбрать его и обработать АЦП в этом канале. Существуют ли подобные контроллеры STM? Проверьте это.

Ответы (1)

Единственная особенность каналов 1 и 2 заключается в том, что эти каналы подключены к двум контактам, которые вы продули своим пьезодатчиком.

Но, вы это уже знаете. Штыри закорочены на землю. Это означает, что вы расплавили входной защитный диод, идущий от этого контакта к земле, потянув контакт слишком глубоко под землю. «Слишком далеко» в данном случае — это любое значение Vf этого диода. Согласно техническому описанию, вы абсолютно не можете вытащить какой-либо вывод более чем на 300 мВ под землей, поэтому мы можем с уверенностью предположить, что именно тогда включится входной защитный диод. Он не предназначен для того, чтобы когда-либо проводить ток, и если это произойдет, он быстро расплавится и выйдет из строя. Вот почему вы видите 0 В от вашего датчика, как только он подключен к ним - теперь они постоянно закорочены на землю.

Для справки, вот как выглядят все контакты ввода-вывода на микроконтроллере (более или менее):

![введите здесь описание изображения

Потяните контакт ниже Vf нижнего диода, и он с радостью пожертвует собой, чтобы сохранить все, что подключено к этому контакту, глубже в микроконтроллере. Эти входные защитные диоды обычно имеют очень низкое значение Vf, чтобы гарантировать, что они включаются и создают путь с низким импедансом для электрической неисправности (напряжение, колеблющееся выше VCC или ниже GND), которое обходит остальную часть микроконтроллера.

Как вы подключаете свою схему защиты? Вы полностью пропустили 2 самых важных соединения - где вы подключаете землю, а где вы подключаете вход АЦП.

В зависимости от того, как вы его подключили, защита будет зажимать положительное напряжение, но все же сможет тянуть контакт больше отрицательного, чем может выдержать контакт. Ну, я думаю, это не имеет значения - это единственный способ заземления этих контактов, так что это ваш ответ. Ваша защита не была правильно подключена или иным образом не смогла предотвратить появление >-300 мВ на этих контактах, и их заземляющие диоды вышли из строя.

Что касается чтения CH0 400 при плавании ... так? Он плавает. Неважно, что он читает, он может читать что угодно. Он плавает. Он не будет читать 0. 0 - это потенциал земли. Плавающий вход не имеет потенциала земли. Это не при любом потенциале. Случайный шум будет связан с ним емкостно и магнитно, не будет пути для протекания токов смещения, и неудивительно, что вход АЦП насыщается. Но это не имеет значения. Нет причин читать неподключенный вывод АЦП, потому что любое чтение, которое вы получите, бессмысленно. Чтобы что-то измерить, сначала нужно что-то измерить.