1 2 3 Previous Next 40 Replies Latest reply on Aug 15, 2013 5:11 AM by user_14586677

    20bit voltmeter


      Just started using the psoc 5 and learning C programming a few days ago.


      Figured I would share my frist project with everyone.


      I know the coding is crude, but it was done just as a way to start using the psoc 5.


      I have a few projects in mind for using it, and need to learn so much,


      as there really is a lot going on in this chip.


      any pointers as to using pwm for DDS in the 300KHz range and at 1Hz steps.


      Also need to know how to get at the SC/CT blocks directly so I can make my own part.


      So much to learn, so little time. :)


      Anyways, I will post more as I learn more abot this chip and hope that other will find it useful.

        • 1. Re: 20bit voltmeter

          Your code needs some assistance.




          This construct,          ADC_VoltsData[1] = '0' + (ADC_Volts/100000) % 10;   // Format results for display


          is trying to add an ordinal value, '0', to a long integer, ADC_Volts, to create a string in effect.




          The easy way to do this is to use sprintf() [ printf(), but to a buffer ]  to create a single formatted string,


          then UART_1_PutString( ) to send it all in one command.




          Attached is info for setting up format statement of sprintf().




          Regards, Dana.

          • 2. Re: 20bit voltmeter

            Correction to last post, I see you are trying to extract a single digit and


            save its ascii value, which is one way of doing it, except you are trying


            to combine a float + a char into a char, you need some cast operators.


            If you stay with this method use ftoa() to convert float A/.D result to string,


            then operate on that for formatting.




            But sprintf() still the easy straightforward way.




            Regards, Dana.

            • 3. Re: 20bit voltmeter

              Regarding SC/ST blocks -








              You can consult TRM for register control of blocks.




              Regards, Dana.

              • 4. Re: 20bit voltmeter

                There are 24 UDBs in a PSoC5 (Univesal Digital Blocks) from which many of the usermodules are built. These UDBs can be used to make up own modules by programming them using VeriLog as language. There are some videos (search there and take the time to watch) showing how that works and some examples are in detail described at the PSoC Sensei Blog.


                You have set the conversion mode of your ADC to Multi-Sample which is not completely wrong. This mode is used when continually switching with an analog multiplexor between different inputs. Better would be to use the "Continuous" mode. With the higher sample rate I would suggest you to average some measures (10 to 100) to reduce some noise.




                As a hint for programming (folks here know me to have a strong relationship to "Readable Code") I would suggest you to


                Use separate functions for separate jobs ie. void InitializeHardware(void) or (void DisplayAnalogValue(int32 Voltage)


                Your commenting is excellent, I like to see that


                Keep the indentation of the lines more consistent


                Use highlighting different areas of interest like variable declaration and function code





                • 5. Re: 20bit voltmeter

                  First I would like to thank youtwo for even replying to this post.




                  There is a little more going on with my convertion than you may see untel you dig a little deeper.


                  I'll try and give more details as to what I did and why.


                  I am doing this because this is the way I learn.


                  Fisrt off, the D/A results and for in floating point, it is a signed number, that is a count from the converter.


                  This count can be a negative number, as the D/A can go 100mv below ground.


                  (Yes, Bob, I did not put comments about this in the code :) )


                  So, I just guessed at what the count offset would be for this 100mv and wipe out any negative number from the count.


                  Next is my conversion form the count to a long 32 interger.


                  This is really just multiplying the count by the weight of what one count is equal to in voltage.


                  BTW there is an API to convert the results into Volts, millIvolts and microvolts, just cound not seem to get it to work.


                  The problem with with any results held in a interger or any variable for that matter, is that leading 0's are surpressed.


                  String's do not have this problem, so I have to convert my leading 0 surpressed number into a string.


                  This is done by checking the weight of each digit "(result/weight) % 10;",  if that weights position is 'empty',


                  then an ascii '0' and placed in the string, if the weights position has in value, that is just passed to the string.


                  To use ftoa() I would have to look at how efficient that code is, and if it's is, then sure.


                  now on to sprintf(), I am assuming this is a serial version of printf() you provided a PDF on.


                  If so, I don't think I can use it, as this would not allow for flow control of the serial data to the display.


                  However, printf() does have formatting commands in it. BTW thank you for that fine doc on a C function.


                  As I had said, very new to C programming and the biggest problem I have with it is syntax and knowing whats


                  availabale for a function.


                  The link you had posted is abut the differences between products of the SC blocks.


                  how about a link to the TRM for register control of blocks.




                  Now to reply to Bob,


                  Bob, I know of VeriLog, but know nothing about it, some thing else I have to learn.


                  This is what I meant by so much to learn, so little time :).


                  To fully use this chip, there is a lot of things to learn, and that takes time.


                  I have watched the video/classes, some 20 of them so far, and a lot of it is over my head,


                  as I am not even close to knowing a thing about the subject.


                  Anyways, gevin time, I will get there.


                  As far as my programming, Like I said, this was crude, just wanted results displayed.


                  I wanted to see some thing out of the chip and my time invested into it.


                  Yes, I know I should have broken it into more callable loops :), but was being lazy.


                  But you brought up highlighting, not sure what you mean by this, as I do thing the file gets saved


                  as a basic text file, no real formatting.




                  Again, really thank you for your insights, and will be playing more and hopefully I improve as time goes on.

                  • 6. Re: 20bit voltmeter

                    printf() prints to the system stdout, see this book, attached. Normally


                    one thinks of a console or printer. Can also be a file system.




                    sprintf() prints to a buffer you set up.  Uses same formatting control as






                    So normally using sprintf() it converts the numeric, and formats it all in one


                    call and places results in a buffer. Then you use string UART command to


                    xmit to whatever.




                    Regards, Dana.

                    • 7. Re: 20bit voltmeter

                      "This count can be a negative number, as the D/A can go 100mv below ground."


                      You are referring to the offset spec, which can be +/- .9 LSB. The VDAC value


                      you write is a uint8, unsigned. 1 LSB, in an 8 bit DAC, with a reference of 1.024 V,


                      equals ( 1 / 256 ) x 1.024V = 4 mV.




                      One way of handling offset is to write 0 to VDAC, and measure offset with A/D.


                      Then subtract from further DAC readings. Of course this is a crude approach


                      as T effects, noise, long term drift not handled.




                      Regards, Dana.

                      • 8. Re: 20bit voltmeter





                        Thank you so much for clearing up sprintf() in my mind, I had looked at it and just did not see how to apply it.


                        You have creally shown me what it can do and how it relates. I guess there will be a ver 3 of this little project. lol


                        As in ver 2, I did a lot of clean up from the advive you two had given me, but I did not add in more loops,


                        but it is more clearly written for doing so.




                        as far as the offest goes, I used a 7 1/2 digit volt meter and a secondary 7 digit voltage standard as the source to the adc.


                        yep, I did look at how well the adc did over temp, conversion speed and number of bits. 


                        I have to say, not bad for a cheap little chip!




                        I see that I said D/A, sorry about that, this whole project is using the delta sigma a/d.




                        BTW, thank you for the C programming book!

                        • 9. Re: 20bit voltmeter
                                  OK I made some improvements to this little voltmeter. Now using calls to functions and snprintf However, I really don't think using snprintf over the way I was doing it is better. snprintf used 20k of flash, come on now, 20k compared to like 30 bytes doing it my way. I hate to see what snprintf does to cpu cycles. If you read the comments, you'll note that I want to pass variables to and from my function calls, just can't seem to get how that works, until I firure it out, most variables are global.   
                          • 10. Re: 20bit voltmeter

                            Concerning the use of local vs global variables







                            • 11. Re: 20bit voltmeter

                              Going to your sources:


                              Indentation is not the same all over. There is an editor-setting that uses tabs instead of spaces to indent making corrections a lot easier. Stick to a scheme, for instance


                              Functions and and local var declarations start at column 0 after a compound statement indent, befor a "}" de-indent


                              Your keeping comments in the same line and starting at a common column is excellent, it improves readability a great lot!




                              The definition of avgcount as a float is a wrong type and does not need to be a variable, a #define would be enough


                              You do not calculate an avarage, you simply get 8 ADC-values and discard 7 of them. You ought to add them and divide the result by (avgcount -1). Here you can see that it would be better to declare avgcount as 8 (and compare in the loop with "<=")




                              Do not care (Yet) for the overhead some of the library routines take. When you really run out of flash there are some methods to save lots of kByte.


                              A function not returning a value does not need an explicit "return" statement, it always returns at the last closing "}" of the function. (although you may return from any point within if you want to)


                              I append a link to my favourite C-Manual where you may have a look at functions and returning values from a function that might help you further. http://publications.gbdirect.co.uk/c_book/





                              • 12. Re: 20bit voltmeter

                                Yes, GCC pulls in a lot of capability when you use sprintf(), along with other library


                                f()'s. You can always code a subset of a library function into lower FLASH usage,


                                just as you have done. stdio.h




                                Take a look at a reduced sprintf() that some have used www.cypress.com/




                                Regards, Dana.

                                • 13. Re: 20bit voltmeter

                                  The discussion Global vs Local. Like everytjhing in HW and SW design there rarely


                                  is one "right" answer, just a painting with many shades.




                                  I am completing a design where I used ~ 99.5% of FLASH. I found that with most


                                  variables global, and using pointers to long globals especially , I saved a lot of space


                                  and performance. Especially not passing longs onto stack.. Pointers for longs


                                  especially productive on code size. Stated another way pointer usage on a machine


                                  for any variable > native integer size of machine.




                                  Keep in mind techniques are compiler and architecture dependent, what works in


                                  on one compiler may not in another, same goes for core.




                                  My code does not suffer from various routines modifying the global unexpectqadly as the


                                  code is pretty much serial, so the considerations Bob and others express, not applicable.




                                  Shades of grey :) The beauty of todays tools easy to create a simple test and try to establish


                                  a result.




                                  Regards, Dana.

                                  • 14. Re: 20bit voltmeter

                                    Code size reduction techniques -








                                    These helped me in a similar experience -




                                    1 - If any float math minimize the number of lines you do divides, if possible convert


                                    to multiplies. Convert float to integer math where possible. Pay attention to factoring


                                    of expressions, possible operation reduction, hence code reduction may result.




                                    2 - Lines with function calls, minimize f(g()) compound typed expressions.




                                    3 - Make sure you only use a variable type no larger than needed.




                                    4 - Use unsigned variables wherever possible.




                                    5 - Watchout for structures with mixed const and ram pointers within them,


                                    some compilers choke on this.




                                    6 - If you are heavy on Flash, light on RAM use, convert routines to RAM based


                                    wherever possible.




                                    7 - Try test cases of looping structures, to see what affects code size generation.




                                    8 - Examine .lst file for code that looks wacky in bytes used, understand what


                                    compiler did, and consider rewrite.




                                    9 - Use inline ASM where .lst file C generation looks excessive.




                                    10 - Look at module reuse, sharing, dual purpose, to eliminate # modules 


                                    needed, like counters/timers....Also look at data sheets of modules that could


                                    serve function needed, and compare ROM/RAM requirements needed. Optimize


                                    global HW, like clocks VC1/2/3/Sleep, to eliminate need for other timer/counters.


                                    Use register routing control to "share" module from one task to another, one pin


                                    to another.




                                    11 - Extended library, functions within them are written to be perfectly general,


                                    hence larger code size, you may be able to write one with less code needed for


                                    your specific requirements that result in smaller code size.




                                    12 – Look for approximations to compute transcendental functions if used.




                                    13 - Although no longer supported by HiTech or Cypress, the HiTech Pro compiler


                                    yielded on first try ~ 40% code reduction in my design when I first converted


                                    to it. Then the prior comments yielded another 4 K later in design as I was up


                                    against 32 K Flash limitation.




                                    14 - Some compilers have a setting to optimize code size or speed, the latter


                                    prone to larger code size. Also look at compiler vendors web site for ap notes


                                    and suggestions on optimization, compilers from different vendors behave and


                                    optimize  differently.




                                    15 - const data, strings, etc.., look for ability to reuse common string mnemonics,






                                    16 - Pointer usage can lessen code size, see url's below. Look for function calls


                                    passing longs as value vs pointer, convert to latter. Compiler has to copy all these,


                                    if not referenced. Do not pass longs or floats as values, keep always in mind native machine size.




                                    17 - Most compilers will optimize when indexes, pointers, a power of 2, or divides,


                                    divide becomes a shift.




                                    18 - Look at how linker distributed code and data segments, sometimes you can discover


                                    a poor decision by linker and force code/data into certain psects using pragma constructs,


                                    thereby minimizing wasted ROM space.




                                    19 – When you debug generally you want to turn off optimization, as compiler/linker will


                                    remove code and make jumps that do not make “sense” but are the result of optimization.


                                    When you are up to Flash boundary you may not be able to turn it off, otherwise


                                    application will not load. Keep this in mind, that  your debug strategy may have to change.


                                    I also found if using ICE Cube that debugger may no longer report “watch” variables, this


                                    occurred at ~ 31.5K bytes. In either case you may want to comment out large code sections


                                    to effectively debug.




                                    20 – f() calls take overhead, if you only call a f() once you might eliminate it as a f() call and


                                    place code inline.




                                    21 – Look for f() opportunities, wherever you are coding and repeating similar  operations.


                                    This is obvious, but sometimes missed.




                                    22 – Check compiler on macros, to see if they are being optimized or just being used inline


                                    using more code space vs a f() call solution.




                                    23 – Examine compiler/linker parameter control. For example in HiTech there is the AUTOBANK


                                    setting that controls where local variables are stored, in my case setting to 1 lowered code size by


                                    ~ 250 bytes. READ the MANUAL !




                                    24 – Use inline variable declarations, vs pre declaration (compiler dependent) -




                                                    This                        void dosomething ( void  ) {




                                                                                                    for (  unsigned char I = 0;…..






                                                    Not This               void dosomething ( void  ) {




                                                                                    Unsigned char I = 0;




                                                                                                    for (  I = 0;…..






                                    Some help -
















                                    By using these techniques I was able to regain ~ 4K Bytes of code space in a 32K design, which


                                    I promptly then used up again :(




                                    Regards, Dana.

                                    1 2 3 Previous Next