cancel
Showing results for 
Search instead for 
Did you mean: 

Why is Sigma Delta ADC 32767 at 0 volt?

DMårt
Senior II

Hi!

I'm trying to read Sigma Delta ADC for 16-bit. It works, but it seems that everything is reverse.

For single Sigma Delta ADC I get 32767 (0x7FFF) when I apply 0 volt.

For differential Sigma Delta ADC I get 65553 (0xFFFF) when the difference is 0 volt on both inputs.

When I increase the voltage, then the ADC values....deceases. Not increases. Why?

I want at 0 Volt, the single sigma delta should show 0 ADC and at REF volt, I want the single sigma delta so show 65553 ADC.

If someone want to try out Sigma Delta ADC, here is the code.

static uint32_t Channel = 0;
static uint16_t SDADC_Single[12];
static uint16_t SDADC_Differential[5];
static float SDADC_Single_Calibration_Gain[12] = {0};
static float SDADC_Single_Calibration_Bias[12] = {0};
static float SDADC_Differential_Calibration_Gain[5] = {0};
static float SDADC_Differential_Calibration_Bias[5] = {0};
 
void STM32_PLC_Start_Analog_Input(TIM_HandleTypeDef* htim12, TIM_HandleTypeDef* htim13, TIM_HandleTypeDef* htim16, SDADC_HandleTypeDef* hsdadc1, SDADC_HandleTypeDef* hsdadc2, SDADC_HandleTypeDef* hsdadc3) {
	HAL_TIM_OC_Start(htim13, TIM_CHANNEL_1); /* TIM13 is trigger source for SDADC1 */
	HAL_TIM_OC_Start(htim12, TIM_CHANNEL_1); /* TIM12 is trigger source for SDADC2 */
	HAL_TIM_OC_Start(htim16, TIM_CHANNEL_1); /* TIM16 is trigger source for SDADC3 */
	if (HAL_SDADC_CalibrationStart(hsdadc1, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_CalibrationStart(hsdadc2, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_CalibrationStart(hsdadc3, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc1, HAL_MAX_DELAY) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc2, HAL_MAX_DELAY) != HAL_OK)
			Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc3, HAL_MAX_DELAY) != HAL_OK)
			Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc2) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc3) != HAL_OK) /* Differential only */
		Error_Handler();
}
 
void STM32_PLC_Analog_Input_SDADC1(SDADC_HandleTypeDef* hsdadc1) {
	uint16_t value = HAL_SDADC_InjectedGetValue(hsdadc1, &Channel); /* Channel will have the numbers 0,1,2,3,4,5,6,7,8 but randomly */
	switch(Channel) {
	case 0:
		SDADC_Single[8] = value;
		break;
	case 1:
		SDADC_Single[7] = value;
		break;
	case 2:
		SDADC_Single[6] = value;
		break;
	case 3:
		SDADC_Single[3] = value;
		break;
	case 4:
		SDADC_Single[2] = value;
		break;
	case 5:
		SDADC_Single[1] = value;
		break;
	case 6:
		SDADC_Single[0] = value;
		break;
	case 7:
		SDADC_Single[5] = value;
		break;
	case 8:
		SDADC_Single[4] = value;
		break;
	}
}
 
void STM32_PLC_Analog_Input_SDADC2(SDADC_HandleTypeDef* hsdadc2) {
	uint16_t value = HAL_SDADC_InjectedGetValue(hsdadc2, &Channel); /* Channel will have the numbers 0,1,2 but randomly */
	switch(Channel) {
	case 0:
		SDADC_Single[11] = value;
		break;
	case 1:
		SDADC_Single[10] = value;
		break;
	case 2:
		SDADC_Single[9] = value;
		break;
	}
}
 
void STM32_PLC_Analog_Input_SDADC3(SDADC_HandleTypeDef* hsdadc3) {
	uint16_t value = HAL_SDADC_InjectedGetValue(hsdadc3, &Channel); /* Channel will have the numbers 0,2,4,6,8 but randomly */
	switch(Channel) {
		case 0:
			SDADC_Differential[4] = value;
			break;
		case 2:
			SDADC_Differential[3] = value;
			break;
		case 4:
			SDADC_Differential[2] = value;
			break;
		case 6:
			SDADC_Differential[1] = value;
			break;
		case 8:
			SDADC_Differential[0] = value;
			break;
	}
}
 
/* Get ADC0 to ADC11 */
float STM32_PLC_Analog_Input_ADC_Get(uint8_t i) {
	return SDADC_Single_Calibration_Gain[i]*((float)SDADC_Single[i]) + SDADC_Single_Calibration_Bias[i];
}
 
/* Get raw ADC0 to ADC11 */
uint16_t STM32_PLC_Analog_Input_ADC_Get_Raw(uint8_t i) {
	return SDADC_Single[i];
}
 
/* Set calibration ADC0 to ADC11 */
void STM32_PLC_Analog_Input_ADC_Set_Calibration(uint8_t i, float min_value, float max_value, float bias_value) {
	SDADC_Single_Calibration_Gain[i] = (max_value - min_value) / (0xFFFF);
	SDADC_Single_Calibration_Bias[i] = bias_value;
}
 
/* Get DADC0 to DADC4 */
float STM32_PLC_Analog_Input_DADC_Get(uint8_t i) {
	return SDADC_Differential_Calibration_Gain[i]*((float)SDADC_Differential[i]) + SDADC_Differential_Calibration_Bias[i];
}
 
/* Get raw DADC0 to DADC4 */
uint16_t STM32_PLC_Analog_Input_DADC_Get_Raw(uint8_t i) {
	return SDADC_Differential[i];
}
 
/* Set calibration DADC0 to DADC4 */
void STM32_PLC_Analog_Input_DADC_Set_Calibration(uint8_t i, float min_value, float max_value, float bias_value) {
	SDADC_Differential_Calibration_Gain[i] = (max_value - min_value) / (0xFFFF);
	SDADC_Differential_Calibration_Bias[i] = bias_value;
}
 
/* Callbacks for SDADC */
void HAL_SDADC_InjectedConvCpltCallback(SDADC_HandleTypeDef *hsdadc) {
	if(hsdadc->Instance == SDADC1) {
		STM32_PLC_Analog_Input_SDADC1(hsdadc);
	}else if (hsdadc->Instance == SDADC2) {
		STM32_PLC_Analog_Input_SDADC2(hsdadc);
	}else if (hsdadc->Instance == SDADC3) {
		STM32_PLC_Analog_Input_SDADC3(hsdadc);
	}
}

The sigma delta init-code looks like this.

https://pastebin.com/NT3bfgGv

1 ACCEPTED SOLUTION

Accepted Solutions
DMårt
Senior II

Here is the solution. uint16_t should be int16_t.

16-bit ADC works as a charm! I like it. Very stable.

/*
 * Analog_Input.c
 *
 *  Created on: Jun 13, 2021
 *      Author: Daniel Mårtensson
 */
 
#include "Functions.h"
 
static uint32_t Channel = 0;
static int16_t SDADC_Single[12];
static int16_t SDADC_Differential[5];
static float SDADC_Single_Calibration_Gain[12] = {0};
static float SDADC_Single_Calibration_Bias[12] = {0};
static float SDADC_Differential_Calibration_Gain[5] = {0};
static float SDADC_Differential_Calibration_Bias[5] = {0};
 
void STM32_PLC_Start_Analog_Input(TIM_HandleTypeDef* htim12, TIM_HandleTypeDef* htim13, TIM_HandleTypeDef* htim16, SDADC_HandleTypeDef* hsdadc1, SDADC_HandleTypeDef* hsdadc2, SDADC_HandleTypeDef* hsdadc3) {
	HAL_TIM_OC_Start(htim13, TIM_CHANNEL_1); /* TIM13 is trigger source for SDADC1 */
	HAL_TIM_OC_Start(htim12, TIM_CHANNEL_1); /* TIM12 is trigger source for SDADC2 */
	HAL_TIM_OC_Start(htim16, TIM_CHANNEL_1); /* TIM16 is trigger source for SDADC3 */
	if (HAL_SDADC_CalibrationStart(hsdadc1, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_CalibrationStart(hsdadc2, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_CalibrationStart(hsdadc3, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc1, HAL_MAX_DELAY) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc2, HAL_MAX_DELAY) != HAL_OK)
			Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc3, HAL_MAX_DELAY) != HAL_OK)
			Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc2) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc3) != HAL_OK) /* Differential only */
		Error_Handler();
}
 
void STM32_PLC_Analog_Input_SDADC1(SDADC_HandleTypeDef* hsdadc1) {
	int16_t value = HAL_SDADC_InjectedGetValue(hsdadc1, &Channel); /* Channel will have the numbers 0,1,2,3,4,5,6,7,8 but randomly */
	switch(Channel) {
	case 0:
		SDADC_Single[8] = value;
		break;
	case 1:
		SDADC_Single[7] = value;
		break;
	case 2:
		SDADC_Single[6] = value;
		break;
	case 3:
		SDADC_Single[3] = value;
		break;
	case 4:
		SDADC_Single[2] = value;
		break;
	case 5:
		SDADC_Single[1] = value;
		break;
	case 6:
		SDADC_Single[0] = value;
		break;
	case 7:
		SDADC_Single[5] = value;
		break;
	case 8:
		SDADC_Single[4] = value;
		break;
	}
}
 
void STM32_PLC_Analog_Input_SDADC2(SDADC_HandleTypeDef* hsdadc2) {
	int16_t value = HAL_SDADC_InjectedGetValue(hsdadc2, &Channel); /* Channel will have the numbers 0,1,2 but randomly */
	switch(Channel) {
	case 0:
		SDADC_Single[11] = value;
		break;
	case 1:
		SDADC_Single[10] = value;
		break;
	case 2:
		SDADC_Single[9] = value;
		break;
	}
}
 
void STM32_PLC_Analog_Input_SDADC3(SDADC_HandleTypeDef* hsdadc3) {
	int16_t value = HAL_SDADC_InjectedGetValue(hsdadc3, &Channel); /* Channel will have the numbers 0,2,4,6,8 but randomly */
	switch(Channel) {
		case 0:
			SDADC_Differential[4] = value;
			break;
		case 2:
			SDADC_Differential[3] = value;
			break;
		case 4:
			SDADC_Differential[2] = value;
			break;
		case 6:
			SDADC_Differential[1] = value;
			break;
		case 8:
			SDADC_Differential[0] = value;
			break;
	}
}
 
/* Get ADC0 to ADC11 */
float STM32_PLC_Analog_Input_ADC_Get(uint8_t i) {
	return SDADC_Single_Calibration_Gain[i]*((float)STM32_PLC_Analog_Input_ADC_Get_Raw(i)) + SDADC_Single_Calibration_Bias[i];
}
 
/* Get raw ADC0 to ADC11 */
uint16_t STM32_PLC_Analog_Input_ADC_Get_Raw(uint8_t i) {
	return SDADC_Single[i] + 0x8000;
}
 
/* Set calibration ADC0 to ADC11 */
void STM32_PLC_Analog_Input_ADC_Set_Calibration(uint8_t i, float min_value, float max_value, float bias_value) {
	SDADC_Single_Calibration_Gain[i] = (max_value - min_value) / (0xFFFF);
	SDADC_Single_Calibration_Bias[i] = bias_value;
}
 
/* Get DADC0 to DADC4 */
float STM32_PLC_Analog_Input_DADC_Get(uint8_t i) {
	return SDADC_Differential_Calibration_Gain[i]*((float)STM32_PLC_Analog_Input_DADC_Get_Raw(i)) + SDADC_Differential_Calibration_Bias[i];
}
 
/* Get raw DADC0 to DADC4 */
int16_t STM32_PLC_Analog_Input_DADC_Get_Raw(uint8_t i) {
	return SDADC_Differential[i];
}
 
/* Set calibration DADC0 to DADC4 */
void STM32_PLC_Analog_Input_DADC_Set_Calibration(uint8_t i, float min_value, float max_value, float bias_value) {
	SDADC_Differential_Calibration_Gain[i] = (max_value - min_value) / (0xFFFF);
	SDADC_Differential_Calibration_Bias[i] = bias_value;
}
 
/* Callbacks for SDADC */
void HAL_SDADC_InjectedConvCpltCallback(SDADC_HandleTypeDef *hsdadc) {
	if(hsdadc->Instance == SDADC1) {
		STM32_PLC_Analog_Input_SDADC1(hsdadc);
	}else if (hsdadc->Instance == SDADC2) {
		STM32_PLC_Analog_Input_SDADC2(hsdadc);
	}else if (hsdadc->Instance == SDADC3) {
		STM32_PLC_Analog_Input_SDADC3(hsdadc);
	}
}

View solution in original post

1 REPLY 1
DMårt
Senior II

Here is the solution. uint16_t should be int16_t.

16-bit ADC works as a charm! I like it. Very stable.

/*
 * Analog_Input.c
 *
 *  Created on: Jun 13, 2021
 *      Author: Daniel Mårtensson
 */
 
#include "Functions.h"
 
static uint32_t Channel = 0;
static int16_t SDADC_Single[12];
static int16_t SDADC_Differential[5];
static float SDADC_Single_Calibration_Gain[12] = {0};
static float SDADC_Single_Calibration_Bias[12] = {0};
static float SDADC_Differential_Calibration_Gain[5] = {0};
static float SDADC_Differential_Calibration_Bias[5] = {0};
 
void STM32_PLC_Start_Analog_Input(TIM_HandleTypeDef* htim12, TIM_HandleTypeDef* htim13, TIM_HandleTypeDef* htim16, SDADC_HandleTypeDef* hsdadc1, SDADC_HandleTypeDef* hsdadc2, SDADC_HandleTypeDef* hsdadc3) {
	HAL_TIM_OC_Start(htim13, TIM_CHANNEL_1); /* TIM13 is trigger source for SDADC1 */
	HAL_TIM_OC_Start(htim12, TIM_CHANNEL_1); /* TIM12 is trigger source for SDADC2 */
	HAL_TIM_OC_Start(htim16, TIM_CHANNEL_1); /* TIM16 is trigger source for SDADC3 */
	if (HAL_SDADC_CalibrationStart(hsdadc1, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_CalibrationStart(hsdadc2, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_CalibrationStart(hsdadc3, SDADC_CALIBRATION_SEQ_1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc1, HAL_MAX_DELAY) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc2, HAL_MAX_DELAY) != HAL_OK)
			Error_Handler();
	if (HAL_SDADC_PollForCalibEvent(hsdadc3, HAL_MAX_DELAY) != HAL_OK)
			Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc1) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc2) != HAL_OK)
		Error_Handler();
	if (HAL_SDADC_InjectedStart_IT(hsdadc3) != HAL_OK) /* Differential only */
		Error_Handler();
}
 
void STM32_PLC_Analog_Input_SDADC1(SDADC_HandleTypeDef* hsdadc1) {
	int16_t value = HAL_SDADC_InjectedGetValue(hsdadc1, &Channel); /* Channel will have the numbers 0,1,2,3,4,5,6,7,8 but randomly */
	switch(Channel) {
	case 0:
		SDADC_Single[8] = value;
		break;
	case 1:
		SDADC_Single[7] = value;
		break;
	case 2:
		SDADC_Single[6] = value;
		break;
	case 3:
		SDADC_Single[3] = value;
		break;
	case 4:
		SDADC_Single[2] = value;
		break;
	case 5:
		SDADC_Single[1] = value;
		break;
	case 6:
		SDADC_Single[0] = value;
		break;
	case 7:
		SDADC_Single[5] = value;
		break;
	case 8:
		SDADC_Single[4] = value;
		break;
	}
}
 
void STM32_PLC_Analog_Input_SDADC2(SDADC_HandleTypeDef* hsdadc2) {
	int16_t value = HAL_SDADC_InjectedGetValue(hsdadc2, &Channel); /* Channel will have the numbers 0,1,2 but randomly */
	switch(Channel) {
	case 0:
		SDADC_Single[11] = value;
		break;
	case 1:
		SDADC_Single[10] = value;
		break;
	case 2:
		SDADC_Single[9] = value;
		break;
	}
}
 
void STM32_PLC_Analog_Input_SDADC3(SDADC_HandleTypeDef* hsdadc3) {
	int16_t value = HAL_SDADC_InjectedGetValue(hsdadc3, &Channel); /* Channel will have the numbers 0,2,4,6,8 but randomly */
	switch(Channel) {
		case 0:
			SDADC_Differential[4] = value;
			break;
		case 2:
			SDADC_Differential[3] = value;
			break;
		case 4:
			SDADC_Differential[2] = value;
			break;
		case 6:
			SDADC_Differential[1] = value;
			break;
		case 8:
			SDADC_Differential[0] = value;
			break;
	}
}
 
/* Get ADC0 to ADC11 */
float STM32_PLC_Analog_Input_ADC_Get(uint8_t i) {
	return SDADC_Single_Calibration_Gain[i]*((float)STM32_PLC_Analog_Input_ADC_Get_Raw(i)) + SDADC_Single_Calibration_Bias[i];
}
 
/* Get raw ADC0 to ADC11 */
uint16_t STM32_PLC_Analog_Input_ADC_Get_Raw(uint8_t i) {
	return SDADC_Single[i] + 0x8000;
}
 
/* Set calibration ADC0 to ADC11 */
void STM32_PLC_Analog_Input_ADC_Set_Calibration(uint8_t i, float min_value, float max_value, float bias_value) {
	SDADC_Single_Calibration_Gain[i] = (max_value - min_value) / (0xFFFF);
	SDADC_Single_Calibration_Bias[i] = bias_value;
}
 
/* Get DADC0 to DADC4 */
float STM32_PLC_Analog_Input_DADC_Get(uint8_t i) {
	return SDADC_Differential_Calibration_Gain[i]*((float)STM32_PLC_Analog_Input_DADC_Get_Raw(i)) + SDADC_Differential_Calibration_Bias[i];
}
 
/* Get raw DADC0 to DADC4 */
int16_t STM32_PLC_Analog_Input_DADC_Get_Raw(uint8_t i) {
	return SDADC_Differential[i];
}
 
/* Set calibration DADC0 to DADC4 */
void STM32_PLC_Analog_Input_DADC_Set_Calibration(uint8_t i, float min_value, float max_value, float bias_value) {
	SDADC_Differential_Calibration_Gain[i] = (max_value - min_value) / (0xFFFF);
	SDADC_Differential_Calibration_Bias[i] = bias_value;
}
 
/* Callbacks for SDADC */
void HAL_SDADC_InjectedConvCpltCallback(SDADC_HandleTypeDef *hsdadc) {
	if(hsdadc->Instance == SDADC1) {
		STM32_PLC_Analog_Input_SDADC1(hsdadc);
	}else if (hsdadc->Instance == SDADC2) {
		STM32_PLC_Analog_Input_SDADC2(hsdadc);
	}else if (hsdadc->Instance == SDADC3) {
		STM32_PLC_Analog_Input_SDADC3(hsdadc);
	}
}