Adding Analog Sensor to Crazyflie 2.0
-
- Beginner
- Posts: 3
- Joined: Thu Apr 23, 2015 7:13 am
Adding Analog Sensor to Crazyflie 2.0
Hello,
I am new to developing in C and also mcu's. I am attempting add an analog sensor to the Crazyflie 2.0 and found a great tutorial online (https://cfusting.wordpress.com/2013/07/ ... ty-sensor/). I believe cfusting posted his project on this board as well. After reviewing cfusting's github code for adc, I noticed that his adc.c was now renamed to adc_f103.c on Crazyflie 2.0. After further research, I realized that Crazyflie 2.0 is using the stm32f405 chip instead of the smt32f103.
Is it still possible to use cfustings tutorial on adding an analog sensor on Crazyflie 2.0?
I am new to developing in C and also mcu's. I am attempting add an analog sensor to the Crazyflie 2.0 and found a great tutorial online (https://cfusting.wordpress.com/2013/07/ ... ty-sensor/). I believe cfusting posted his project on this board as well. After reviewing cfusting's github code for adc, I noticed that his adc.c was now renamed to adc_f103.c on Crazyflie 2.0. After further research, I realized that Crazyflie 2.0 is using the stm32f405 chip instead of the smt32f103.
Is it still possible to use cfustings tutorial on adding an analog sensor on Crazyflie 2.0?
Re: Adding Analog Sensor to Crazyflie 2.0
Hi and welcome!
As you figured out the adc_f103.c is for the STM32F103 MCU and is not really valid for CF2 even though it could be ported. We are working on a API that will make it easier to use all expansion port functions but for now one has to work with the ST lib. I found this article which does basic ADC readings and I suggest you start by basing it out of that. Using DMA makes things a bit more complicated.
As you figured out the adc_f103.c is for the STM32F103 MCU and is not really valid for CF2 even though it could be ported. We are working on a API that will make it easier to use all expansion port functions but for now one has to work with the ST lib. I found this article which does basic ADC readings and I suggest you start by basing it out of that. Using DMA makes things a bit more complicated.
-
- Beginner
- Posts: 3
- Joined: Thu Apr 23, 2015 7:13 am
Re: Adding Analog Sensor to Crazyflie 2.0
Thank you very much for your response and for leading me on the right path. I was able to find some good resources online regarding adc on the stm32f4. I was able to successfully create an ADC to obtain the temperature from the onboard temp sensor.
I then attempted to add my own sensor which is also a temperature sensor by enabling a GPIO pin analog input mode. If I choose pin PA7 (GPIOA, GPIO_Pin_6), would this pin be related to ADC_Channel_7? I am not using RMA, TIM or NVIC and I setup the ADC1 in single conversion mode.
I then attempted to add my own sensor which is also a temperature sensor by enabling a GPIO pin analog input mode. If I choose pin PA7 (GPIOA, GPIO_Pin_6), would this pin be related to ADC_Channel_7? I am not using RMA, TIM or NVIC and I setup the ADC1 in single conversion mode.
Re: Adding Analog Sensor to Crazyflie 2.0
Great that you got something working! Yes looking in the STM32F405 datasheet PA7 corresponds to ADC channel 7.
-
- Beginner
- Posts: 3
- Joined: Thu Apr 23, 2015 7:13 am
Re: Adding Analog Sensor to Crazyflie 2.0
Thanks once again for your help.
I am trying to get a reading from the TMP36 temperature sensor. It is connected to pin PA7. When I look at the plotter on the python client, I do see a voltage result, but when I applied heat to the sensor, the readings did not change which leads me to believe I am not acutally getting results from the sensor itself.
I have pasted the code of which much of it was borrowed from this blog. I would really appreciate any help on the code. Thanks!
I am trying to get a reading from the TMP36 temperature sensor. It is connected to pin PA7. When I look at the plotter on the python client, I do see a voltage result, but when I applied heat to the sensor, the readings did not change which leads me to believe I am not acutally getting results from the sensor itself.
I have pasted the code of which much of it was borrowed from this blog. I would really appreciate any help on the code. Thanks!
Code: Select all
static bool isInit = false;
static float temp;
static float vref;
void tmp36Task(void *param);
void tmp36Init()
{
if (isInit) return;
/* Define ADC init structures */
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* IMPORTANT: populates structures with reset values */
ADC_StructInit(&ADC_InitStructure);
ADC_CommonStructInit(&ADC_CommonInitStructure);
/* enable ADC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* init GPIO */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_Speed = GPIO_Low_Speed;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* init ADCs in independent mode, div clock by two */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* init ADC1: 12bit, single-conversion */
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = 0;
ADC_InitStructure.ADC_ExternalTrigConv = 0;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* Enable VREF_INT & Temperature channel */
ADC_TempSensorVrefintCmd(ENABLE);
/* Enable ADC1 **************************************************************/
ADC_Cmd(ADC1, ENABLE);
xTaskCreate(tmp36Task, (const signed char * const)"tmp36",
configMINIMAL_STACK_SIZE, NULL, 3, NULL);
isInit = true;
}
bool tmp36Test(void)
{
return isInit;
}
float adc_read(ADC_TypeDef* ADCx, uint8_t channel, uint8_t ADC_SampleTime) {
/* Configure Channel */
ADC_RegularChannelConfig(ADCx, channel, 1, ADC_SampleTime);
/* check if conversion was started, if not start */
ADC_SoftwareStartConv(ADCx);
/* wait for end of conversion */
while((ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) == RESET));
return (float)ADC_GetConversionValue(ADCx);
}
void tmp36Task(void *param)
{
float val;
vTaskSetApplicationTaskTag(0, (void*)TASK_ADC_ID_NBR);
vTaskDelay(1000);
while(1)
{
val = adc_read(ADC1, ADC_Channel_7, ADC_SampleTime_480Cycles);
vref = adc_read(ADC1, ADC_Channel_17, ADC_SampleTime_480Cycles);
//I am attemping to get the voltage reading and not actually converting it
//to the temperature value yet.
temp = val / (vref / 1.2); //ADC internal vref is 1.2v
}
}
LOG_GROUP_START(TMP36)
LOG_ADD(LOG_FLOAT, tmp36, &temp)
LOG_GROUP_STOP(TMP36)
Re: Adding Analog Sensor to Crazyflie 2.0
Try reading the internal temperature channel to rule out any possible problems with pin mapping/channel etc.
Re: Adding Analog Sensor to Crazyflie 2.0
Hi, I am working on interfacing a couple of proximity sensors (A Sharp IR sensor and a Maxbotics ultrasonic sensor) to the crazyflie 2.0. I have found some forum posts and recommendations on how to use GPIOs on the deck port, when I stumbled across the above comment on a new API for the deck port being worked on.As you figured out the adc_f103.c is for the STM32F103 MCU and is not really valid for CF2 even though it could be ported. We are working on a API that will make it easier to use all expansion port functions but for now one has to work with the ST lib. I found this article which does basic ADC readings and I suggest you start by basing it out of that. Using DMA makes things a bit more complicated.
Is there a repos available somewhere with this work? - I realize this is not a stable API as it is work in progress, however I will be happy to check it out for my sensor integration.
Re: Adding Analog Sensor to Crazyflie 2.0
Hi,
I have started working on it for the digital IO at least, I pushed it in the bigmerge branch you can see the pin mapping in this file: https://github.com/bitcraze/crazyflie-f ... _digital.c
My plan is to implement at least the arduino api for the expansion port, it does not give full control on the hardware but it is easy to use (and already documented
. This is what I have done with the GPIO and the same should be done with the analog pin but I did not have time for it yet.
Note that this code is not fully tested, but it does not break the firmware so I merged it anyway.
I have started working on it for the digital IO at least, I pushed it in the bigmerge branch you can see the pin mapping in this file: https://github.com/bitcraze/crazyflie-f ... _digital.c
My plan is to implement at least the arduino api for the expansion port, it does not give full control on the hardware but it is easy to use (and already documented

Note that this code is not fully tested, but it does not break the firmware so I merged it anyway.
Re: Adding Analog Sensor to Crazyflie 2.0
Hi, thanks for merging the deck_digital.c code. I have not tested it yet, however I followed your lead on implementing Arduino API for the deck port. I currently have two initial patches:My plan is to implement at least the arduino api for the expansion port, it does not give full control on the hardware but it is easy to use (and already documented. This is what I have done with the GPIO and the same should be done with the analog pin but I did not have time for it yet.
Adding deck_analog API: https://github.com/bitcraze/crazyflie-f ... f43c5c51f3
Initial test of MaxBotix Sonar Range Finder: https://github.com/bitcraze/crazyflie-f ... f32da57f20
Regarding the first patch, adding the deck_analog API:
* This is based on code from http://survivalengineer.blogspot.no/201 ... -ever.html
* Implements the Arduino analogRead() function
* Synchronous (blocking) read of a single channel only. No scan, no continous mode, no DMA, no interrupts
* Some TODOs remain
* I made a local copy of your gpioMapping struct internally in deck_analog.c. I am thinking of creating a patch where I move this to a new deck_constants.c file, with a corresponding typedef in deck_constants.h. Is this OK with you?
* I have an adcMapping struct in deck_analog.c, which could be merged as an extra column into your gpioMapping struct. Is this OK, or would you prefer keeping them separate for now?
* I would also like to move the DECK_PIN_XX definitions (used for lookup in gpioMapping) to the deck_constants, if OK with you
Regarding the second patch, the initial test of the MaxBotix Sonar Range Finder:
* A quick hack just to test the deck_analog API
* Start of a driver for the MaxBotix sonar range finder
* Log group "mb" created, variable "distance" (mm) available in cfclient
* Initial tests show the measurements to be accurate (down to 1-2cm), however there is considerable noise. Possibly related to conversion frequencies, clocks, ADC sample times etc. (?) - This is my text issue to look into
* Some TODOs remain
* This patch calls adcInit() during startup. Should we make this a comile-time setting perhaps, to ensure ADC is only started when needed?
* I am planning on using range finders to implement an automatic landing function/mode.
Re: Adding Analog Sensor to Crazyflie 2.0
Hi, Thanks for the great work and for sharing it!
Regarding the first patch:
The implementation is great. Blocking call is good for this API: the idea is to make the API as simple as possible and the user code should then run in its own task. So we can have all deck api blocking and synchronous.
Concerning the second patch:
Looks good and simple, this really shows that the deck API is needed!
The only comment I have is that the connection to the stabiliser loop: it is a bit intrusive. We will need at least an #ifdef to merge it. Anyway this is a problem we have had since the begining and we will need to find a way to make internal connection a bit more modular (maybe something like allowing deck driver to feed an altitude and the stabilizer to use the best available altitude source)
As for adcinit() I do not think we need to be too fancy: the motors consume so much that there is not much we can do for power optimisation on the CPU side so always calling adcinit() is not a problem. Otherwise it would be pretty easy to call it the first time analogRead() is called, but I do not see that as mandatory.
Auto take-off would be really nice!
Regarding the first patch:
The implementation is great. Blocking call is good for this API: the idea is to make the API as simple as possible and the user code should then run in its own task. So we can have all deck api blocking and synchronous.
This is good, off course we should avoid duplicationfredgrat wrote: * I made a local copy of your gpioMapping struct internally in deck_analog.c. I am thinking of creating a patch where I move this to a new deck_constants.c file, with a corresponding typedef in deck_constants.h. Is this OK with you?
Merging them is a good idea. We can later also add spi/uart/i2c in the same struct as well as a mechanism to handle conflict.fredgrat wrote: * I have an adcMapping struct in deck_analog.c, which could be merged as an extra column into your gpioMapping struct. Is this OK, or would you prefer keeping them separate for now?
OK as well. Using the breakout names is a good idea.fredgrat wrote: * I would also like to move the DECK_PIN_XX definitions (used for lookup in gpioMapping) to the deck_constants, if OK with you
Concerning the second patch:
Looks good and simple, this really shows that the deck API is needed!
The only comment I have is that the connection to the stabiliser loop: it is a bit intrusive. We will need at least an #ifdef to merge it. Anyway this is a problem we have had since the begining and we will need to find a way to make internal connection a bit more modular (maybe something like allowing deck driver to feed an altitude and the stabilizer to use the best available altitude source)
As for adcinit() I do not think we need to be too fancy: the motors consume so much that there is not much we can do for power optimisation on the CPU side so always calling adcinit() is not a problem. Otherwise it would be pretty easy to call it the first time analogRead() is called, but I do not see that as mandatory.
Auto take-off would be really nice!