Go Down

Topic: STM32F4 (Read 20609 times) previous topic - next topic

westfw

It's common for a microcontroller to have many fewer A-D converters than it has analog pins, with an analog multiplexer in between the pins and the A-D converter.  The Atmel AVR used on the Arduino only has ONE A-D converter, fronted by a 16
:1 analog multiplexer (some of whose inputs are not connected), so that when you do an "analogRead(port)", what actually happens is more like:
Code: [Select]
SelectAnalogInput(port);
delay(MUXSETTLETIME);
StartADConversion();
delay(ADCONVERTTIME);
return(readADC();

The  STM32F4 actually has three separate A2D converters, each with an 8:1 mux (and some complex connections to pins that I didn't look into very much.)  So you could read up to three Analog inputs without messing separately with the muxes (except at setup time), or you'll have to do something similar to what the Arduino core SW does.

In general, it is a useful technique in learning a new processor/board to try to COPY (only be sure to call it "port") an existing familiar set of software.  So the question shouldn't be "how do I read analog inputs on STM32F4?", but "How do I duplicated the AnalogRead() function on STM32F4?"   It may seem very similar, but the process is different.  Instead of starting from scratch, you get to look at the steps that the arduino code uses, and figure out whether they have equivalents on the STM.  Since the individual steps are smaller, they may be easier to understand.  Of course, you end up needing to understand both the existing Arduino code AND the new processor code.  But ... it's good for you!

Resinator

Quote
It's common for a microcontroller to have many fewer A-D converters than it has analog pins, with an analog multiplexer in between the pins and the A-D converter.


Yeah that makes perfect financial sense, THE ADC will be relatively expensive so one ADC can be used via a mux to read different pins on the same port

Quote
The  STM32F4 actually has three separate A2D converters, each with an 8:1 mux (and some complex connections to pins that I didn't look into very much.) 


Got that bit the STM32F4 has ADC1 ADC2 ADC3, I dont know much about their associated mux block though

Quote
So you could read up to three Analog inputs without messing separately with the muxes (except at setup time), or you'll have to do something similar to what the Arduino core SW does.


I am reading three separate ADC's but I had to set them up on separate ports, port A port B and portC, I really havent a clue how I could setup the mux so that I can use say three ADC's on one port it just wouldnt work even better would be to use one ADC on one port with three separate pins but I havent a clue how to do that, at the minute I am still on a high because I got an input recognised by the board (dont spoil it!!) the analogue reference is 2.95V and I wish I knew how to change that but for the moment I am happy!


Quote
In general, it is a useful technique in learning a new processor/board to try to COPY (only be sure to call it "port") an existing familiar set of software.  So the question shouldn't be "how do I read analog inputs on STM32F4?", but "How do I duplicated the AnalogRead() function on STM32F4?"   It may seem very similar, but the process is different.  Instead of starting from scratch, you get to look at the steps that the arduino code uses, and figure out whether they have equivalents on the STM.  Since the individual steps are smaller, they may be easier to understand.  Of course, you end up needing to understand both the existing Arduino code AND the new processor code.  But ... it's good for you!


I would be willing to do that in fact I would go as far as to say I would probably enjoy it!,...

trouble is I havent got a clue where I would even start!

cyclegadget

  I am glad you are making great progress! I have been following the thread and have learned some from reading it.

Here is a bit of code from Arduino wiring_analog.c related to analogread :

Code: [Select]
int analogRead(uint8_t pin)
{
uint8_t low, high;

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#else
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif

#if defined(__AVR_ATmega32U4__)
pin = analogPinToChannel(pin);
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#elif defined(ADCSRB) && defined(MUX5)
// the MUX5 bit of ADCSRB selects whether we're reading from channels
// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
 
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits).  this also sets ADLAR (left-adjust result)
// to 0 (the default).
#if defined(ADMUX)
ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif

// without a delay, we seem to read from the wrong channel
//delay(1);

#if defined(ADCSRA) && defined(ADCL)
// start the conversion
sbi(ADCSRA, ADSC);

// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));

// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read.  reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low  = ADCL;
high = ADCH;
#else
// we dont have an ADC, return 0
low  = 0;
high = 0;
#endif

// combine the two bytes
return (high << 8) | low;
}
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

UnaClocker


It's common for a microcontroller to have many fewer A-D converters than it has analog pins, with an analog multiplexer in between the pins and the A-D converter.  The Atmel AVR used on the Arduino only has ONE A-D converter, fronted by a 16
:1 analog multiplexer (some of whose inputs are not connected)

I had no idea it worked like this. Your explanation was very enlightening. Thanks.
Brian from Tacoma, WA
Arduino evangelist - since Dec, 2010.

Resinator

Quote
I am glad you are making great progress!


Thanks, I have really gotten into this STM32F4 and I have made some excellent progress in the last few days, I have been learning C as I go and after a fair few hours I have wrote a program which replaced three Uno's with one STM32F4, its a motor drive program to drive a low voltage (30V) prototype inverter which in turn drives a dummy RL load

The program uses an timed interrupt three ADC's and four pins and its quick enough to set the ADC to maximum sample time 480 cycles and calculate the reference on the fly

I initially uploaded the program to the board about three days ago and I hit a few problems but at last :D it works!!!!!!  XD YES! I have a nice warm glowing feeling!  :smiley-red:

The STM does the job pretty fast which gives better results


I took some shots, I need two sinusoidal currents 90 degrees out of phase which is what I get




Resinator

Another showing the phase shift

Resinator

The PWM is really fast and it works a dream


Resinator

Same again

Resinator

I was happy with what the three arduinos did

heres a pic

Resinator

The Uno can be seen to be slower and I dedicated a complete controller to one phase where the STM32 is now controlling three!

Resinator

The Unos pulse width was much bigger hence lots of low order harmonics in the audio spectrum, the higher order harmonics the STM generates will be filtered by the motors windings inductance

Resinator

#41
Jun 15, 2012, 09:33 pm Last Edit: Jun 16, 2012, 03:14 am by Resinator Reason: 1
The programs a bit large to upload here, heres the main while loop of the program

Code: [Select]
 while (1)

 {GPIO_ToggleBits(GPIOD, GPIO_Pin_15);


/***************************Main Winding*******************************************************/
    SINWt= sinf(n*Wt);
        IMAINREF= 340*SINWt;

      ADC_SoftwareStartConv(ADC1);
       while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

           MAINHALL = *ADC1_DATA*2950/4095 - MAINOFFSET;
           IMAIN=(34*MAINHALL/40-2125);
           MAINERR=IMAIN-IMAINREF;
           if(MAINERR<=-2){
            GPIO_ResetBits(GPIOD, GPIO_Pin_9);
           }
         if(MAINERR>=2){
            GPIO_SetBits(GPIOD, GPIO_Pin_9);
           }

/*************************Aux Winding****************************************************/
             COSWt =cosf(n*Wt);
         IAUXREF= 340*COSWt;

                 ADC_SoftwareStartConv(ADC2);
                   while(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET);

                     AUXHALL = *ADC2_DATA*2950/4095 - AUXOFFSET;
                     IAUX=(34*AUXHALL/40-2125);
                     AUXERR=IAUX-IAUXREF;
                       if(AUXERR<=-2){
                        GPIO_ResetBits(GPIOD, GPIO_Pin_13);
                       }
                  if(AUXERR>=2){
                        GPIO_SetBits(GPIOD, GPIO_Pin_13);
                     }

/***************************************************************************************/


  ADC_SoftwareStartConv(ADC3);
   while(ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET);

   VIN = *ADC3_DATA;
   int CHANGEHZ = (VIN*22/3390)-(FREFINIT-25);
                  if(CHANGEHZ<=-1 || CHANGEHZ>=1){

                  GPIO_ResetBits(GPIOD, GPIO_Pin_13|GPIO_Pin_11|GPIO_Pin_9);
                  VIN = *ADC3_DATA;
                  FREFINIT= (VIN*22/3390);
                  FREFINIT+= 25;

                  if(FREFINIT>=47)
                    {FREFINIT=47;}

                  if(FREFINIT<=25)
                    {FREFINIT=25;}

                     FREF= FREFINIT;
                     Wt = 157.0796327*FREF/1000000;
                  }

 }






It takes about 31.2us to do all that as I used pin 15 to monitor it

All in all i am loving it, I still have so much more to mess around with and implement but I have the bare bones working its all optional extras from here, I already have the drive able to alter output frequency online which is something I just couldnt manage with the Arduinos

cyclegadget


Very impressive! You definitely ran with that STM chip! I have worked some with an Olimex STM32 board that runs the Maple IDE and I was impressed with the speed also. I need to spend more time to get my head around the programming necessary to get the most out of it though.

If you are needing to move to custom board, here is a link to some hardware designs that a member of the Leaflabs forum has posted.  https://github.com/gbulmer
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

Resinator

#43
Jun 16, 2012, 02:56 am Last Edit: Jun 16, 2012, 03:15 am by Resinator Reason: 1
Its taken me four weeks, Attolic is the best advice ever, I have really gotten to grips with it, by using the ST Link debugger a noob can learn so much about program flow and the C language, I think the next step is a space vector modulation drive (this ones an hysteresis current drive) the board can definitely do it

I love power electronics, I really need to get the facilities to make my own PCB's I dont suppose anyone can advise the best way?
Quote


here is a link to some hardware designs


I clicked the link but I dont understand what it even is?, hardware designs? of a microcontroller board? theres a lot there!

cyclegadget


I should have gave this more specific link that has the Eagle designs. https://github.com/gbulmer/openstm32hw

The readme at the bottom of the page best describes what the files contain.
Good links: Eagle tutorial= http://www.youtube.com/playlist?list=PLDE1858BD83D19C70
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

Go Up