Shop OBEX P1 Docs P2 Docs Learn Events
Attempting to read an ADC0831 using C — Parallax Forums

Attempting to read an ADC0831 using C

Blake KochBlake Koch Posts: 39
edited 2013-11-13 04:50 in Propeller 1
I would like to read an ADC 0831 chip using C Simple IED. Im having trouble finding the code need to pulse the CLK pin as well as the Code needed to return and store the data from DO pin.

Can anyone help ?

Thanks
Blake

Comments

  • dgatelydgately Posts: 1,630
    edited 2013-11-09 18:51
    No sure that anyone has specifically shown C code for this, but Johnny Mac's jm_adc083x_ez in the OBEX is a good, simple Spin object. You should be able to translate the Spin code to C easily, as I don't see anything in the code that cold not be quickly translated. Check out this file: "jm_adc0831_ez.spin"...


    OBEX link: http://obex.parallax.com/object/300

    dgately
  • Blake KochBlake Koch Posts: 39
    edited 2013-11-10 07:08
    I agree, this should be easy, however I have no syntax guide to help convert the languages. So that makes my first question into two separate questions. Is there also a complete syntax guide for the Propeller C Simple IDE.

    Thanks

    Blake
  • dgatelydgately Posts: 1,630
    edited 2013-11-10 07:47
    Blake Koch wrote: »
    I agree, this should be easy, however I have no syntax guide to help convert the languages. So that makes my first question into two separate questions. Is there also a complete syntax guide for the Propeller C Simple IDE.

    Thanks

    Blake

    Hmm... The first advice I would give is to start with some simple C programs before attempting to deal with a device like an ADC. Have you attempted Parallax's Propeller C learning system yet? (http://learn.parallax.com/propellerc) The Parallax staff has put a lot of work into developing very simple tutorials that will get you up and programming in C for the propeller. Learning C syntax while trying to access a device that is not yet supported by a library is going to make your task difficult. So, spend a day or two just learning C before you attempt to access the ADC. Just my advise (of course, my advise and $4.50 will buy you a latte at Starbucks and not much more:blank:)

    For C syntax learning, the best guide is "The C Programming Language" text by Brian Kernighan & Denis Ritchie. You can find this text as a .PDF on the internet or buy a paper copy from Amazon. (http://www.cs.ucsb.edu/~buoni/cs16/The_C_Programming_Language.pdf). Although there are many books on C programming, this is "the text" on C that millions of programmers cut their teeth on.

    dgately
  • Blake KochBlake Koch Posts: 39
    edited 2013-11-10 09:14
    Thanks for the advice and the latte. The Latte was just what I needed this morning. I had been working through the C training tutorial when I reached ADC project. The tutorial is only supported by the ADC on the activity board, being that I have two or three other Prop boards other than the activity board I was hoping to simply use my knowlage of the ADC0831 to complete this tutorial. And what a great opportunity it would be to learn more C line codes. The tutorial does not go into any detail as to how (#include "adcDCpropab.h") works.
    /*
    Measure Volts.c

    Make voltmeter-style measurements with the Propeller Activity Board.
    */

    #include "simpletools.h" // Include simpletools
    #include "adcDCpropab.h" // Include adcDCpropab

    int main() // main function
    {
    adc_init(21, 20, 19, 18); // CS=21, SCL=20, DO=19, DI=18

    float v2, v3; // Voltage variables

    Can this line code be modified to fit the ADC 831? adc_int(21,20,19,18) What pulse duration is at pin 20, Can it be adjusted. and since the 831 does not have a DI pin 18 can that segment of code be eliminated or modified.

    If it can't be modified it would seem to me that all I need to do is write a simple code 1 to select chip (easy) 2 send a pulse equal to the 831 range 420us, (this code I don't know yet) 3 retrieve the data from the do pin and put it in a variable.(this code I don't know yet). Sound like it should be simple.http://forums.parallax.com/images/icons/icon6.png

    Thanks for any help guys.
    Blake
  • dgatelydgately Posts: 1,630
    edited 2013-11-10 09:33
    Just for fun, I ported Johnny Mac's spin ADC0831 OBEX object to C. Not sure if it works, as I have no ADC0831 to test this...

    Left all of Johnny Mac's comments as-is as this is just a test. He may want to port this and update, but thought it would be a good exercise in porting spin to C, for the moment.
    /* =================================================================================================
    
       File....... jm_adc0831_ez.c
       Purpose.... C port of jm_adc0831.spin library code
       Author..... Jon McPhalen
                   Copyright (c) 2009 Jon McPhalen
                   -- see below for terms of use
       E-mail..... jon@jonmcphalen.com
       Started.... 
       Updated.... 01 JUL 2009
    
       Version 1.0 : original code
       Version 1.1 : code clean-up, added scale method
       Version 1.2 : renamed start (to init) and stop (to cleanup) to prevent I2C confusion
    
     =================================================================================================
    
                                   5v
                    ADC0831        
              ┌─────────────────┐  │
      cs ────┤1 /CS       VCC 8├──┫                
     ch0 ────┤2 VIN+      CLK 7├──│────── clk   
           ┌──┤3 VIN-  dataOut 6├──│──── dataOut
           ┣──┤4 GND      VREF 5├──┘ 10K               
           │  └─────────────────┘   
           
    
     Shown configured for single-ended input                      
    */
    
    #include "simpletools.h"
    
    //CON
    
    #define  US_005  (80000000 / 1000000 * 5)                           // 5us
     
    //VAR
    
    int32_t  cs;
    int32_t  clk;
    int32_t  dataOut;
    
    void init(int32_t cspin, int32_t clkpin, int32_t dataOutpin){
    
    // Get pin assignments and set /CS and CLK pins to outputs
    // -- /CS initialized high to disable ADC0831
    
      cs = cspin;
      //outa[cs] := 1                            // output high (SPIN)
      //dira[cs] := 1
      high(cs);
      set_direction(cs,1);
    
      clk = clkpin;
      //outa[clk] := 0                           // output low (SPIN)
      //dira[clk] := 1
      low(clk);
      set_direction(clk,1);
    
    
      dataOut = dataOutpin;
      //dira[dataOut] := 0                       // make input (SPIN)
      set_direction(dataOut,0);
    }
    
    void cleanup() {
    
    // Makes IO pins inputs
    
      //dira[cs] := 0                            // make inputs (SPIN)
      //dira[clk] := 0  
      set_direction(cs,0);
      set_direction(clk,0);
    
    }
    
    int32_t readADC(){
    
      int level = 0;
    
    // Read ADC0831 channel
    // -- mode is based on hardware configuration
    //    * VIN- to ground for single-ended
    //    * VIN- to voltage for differential
                                                           
      //outa[cs] := 0                                         // activate adc (SPIN)
      low(cs);
      pause_ticks(US_005);
    
      // input data bits, MSBPOST
      // -- extra clock bit starts conversion
    
      level = 0;                                              // clear work var
      
      for(int i = 0; i < 9; i++){
        //outa[clk] := 1                                      // clock a clock (SPIN)
        high(clk);
        pause_ticks(US_005);
        //outa[clk] := 0                                      // set clock low (SPIN)
        low(clk);
        pause_ticks(US_005);
    //  level = (level << 1) | ina[dataOut]                   // input data bit (SPIN)
        level = (level << 1) | get_state(dataOut);
      }
      //outa[cs] = 1;                                         // de-activate adc (SPIN)
      high(cs);  
    //  return (level & $FF)                                  // return adc result(SPIN)
      return (level & 0xFF); 
    }
     
    int32_t scale(int32_t raw, int32_t minOut, int32_t maxOut){
    
    // Scales raw (0 to 255) value to new range: minOut to maxOut
    
      if ((raw < 256) && (minOut < maxOut))                    // force legal values
        return ((raw * (maxOut - minOut)) / 255) + minOut;
      else
        return raw;  
    
    } 
    
    int main(void) {
    
    // DO SOMETHING
    
      init(0, 1, 2);
      print("Here's something: %d\n",readADC());
      
      for(;;){}
    
    } 
    
    /*
      Copyright (c) 2009 Jon McPhalen
    
      Permission is hereby granted, free of charge, to any person obtaining a copy of this
      software and associated dataOutcumentation files (the "Software"), to deal in the Software
      without restriction, including without limitation the rights to use, copy, modify,
      merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
      permit persons to whom the Software is furnished to dataOut so, subject to the following
      conditions:
    
      The above copyright notice and this permission notice shall be included in all copies
      or substantial portions of the Software.
    
      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
      INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
      PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
      CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
      OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.   
    */                 
    

    Can you test this?


    dgately
  • jmgjmg Posts: 15,173
    edited 2013-11-10 14:18
    dgately wrote: »
    Left all of Johnny Mac's comments as-is as this is just a test. He may want to port this and update, but thought it would be a good exercise in porting spin to C, for the moment.

    This could make a good CogC test, for a couple of useful indicator metrics :

    If the ADC read and scale target one COG via CogC, (means main printf is in another ?),

    M1 :
    How much of a COG does this use, and how does that use split between int32_t mathops and user code.
    What is speed of int32_t scale ?

    M2:
    if the int32_t changes to int64_t, how does that use split between int64_t mathops and user code.
    What is speed of int64_t scale ?

    M3: Repeat M2 for Real Numbers.
  • jazzedjazzed Posts: 11,803
    edited 2013-11-10 17:26
    CogC is designed for COG sized driver functions generally speaking. Anything that blocks can be executed from the main program at almost the same speed as in CogC.

    You can force it to do things to find it's limits as an exercise if you like; however, even our smallest floating point print function (about 4KB) would not fit in CogC.

    Best to leave the business logic in CMM and drivers in cogs.

    There is an fpucog.c file that we can add to projects that speed up default floating point by about 10x. At the moment it is in simpletools, but i wouldn't count on it staying there by default because it uses a COG.

    jmg wrote: »
    This could make a good CogC test, for a couple of useful indicator metrics :

    If the ADC read and scale target one COG via CogC, (means main printf is in another ?),

    M1 :
    How much of a COG does this use, and how does that use split between int32_t mathops and user code.
    What is speed of int32_t scale ?

    M2:
    if the int32_t changes to int64_t, how does that use split between int64_t mathops and user code.
    What is speed of int64_t scale ?

    M3: Repeat M2 for Real Numbers.
  • jmgjmg Posts: 15,173
    edited 2013-11-10 18:24
    jazzed wrote: »
    ...
    You can force it to do things to find it's limits as an exercise if you like; however, even our smallest floating point print function (about 4KB) would not fit in CogC.

    That was why I excluded printf, I expected that to have a high cost.

    The intention is to place the sensor driver into a COG, but it makes most sense to also include the sensor fitting/scale maths as well as that makes for better modularity and support.
    It is still not clear what subsets can fit into a cog, via CogC, and with what overhead. (ie how much do they remove from user code space)

    What about Float Mul and Div, and int32 and/or int64 mul/div/mod - do those compile into CogC, or are they always calls outside the COG.
  • jazzedjazzed Posts: 11,803
    edited 2013-11-10 19:23
    jmg wrote: »
    That was why I excluded printf, I expected that to have a high cost.

    The intention is to place the sensor driver into a COG, but it makes most sense to also include the sensor fitting/scale maths as well as that makes for better modularity and support.
    It is still not clear what subsets can fit into a cog, via CogC, and with what overhead. (ie how much do they remove from user code space)

    What about Float Mul and Div, and int32 and/or int64 mul/div/mod - do those compile into CogC, or are they always calls outside the COG.
    CogC really is for hardware device drivers or other things that will fit nicely in a COG.

    The only library code as I recall that was ever written for CogC is an integer printf function and some support items (a version of which is in the repository)..

    Float MUL/DIV, etc... are either in the floating point emulation library, or the fpucog.c which is in-line ASM COG code included automatically when added to a project.
  • jmgjmg Posts: 15,173
    edited 2013-11-11 12:17
    jazzed wrote: »
    The only library code as I recall that was ever written for CogC is an integer printf function and some support items (a version of which is in the repository)..

    That's a useful link, I can see 32 bit Mu & Div, are there plans for 64 bit versions ?

    The classic sensor scale eqn is A*B/C, (as above) and it can be important to at least operate 64b on the interim result.

    So a lib that allowed this to be the most compact (reside within the COG ) would be great

    Scaled_int32 = Scale_int32_via_int64(A,B,C); and the function does A*B -> 64b/C -> 32b

    on the topic of compact, in divide usually DIV and MOD come for free, so a function form of

    DivideAbyB = Div_Mod_int32(A,B,CommonRem);

    returns A/B and also places remainder in CommonRem, a library or global variable.
  • ersmithersmith Posts: 6,053
    edited 2013-11-13 04:50
    jmg wrote: »
    That's a useful link, I can see 32 bit Mu & Div, are there plans for 64 bit versions ?
    Not in the short term, no. There are 64 bit versions coded in C in libgcc.a, but I don't think that is compiled for COG C (and the C versions will be somewhat on the large side for COG memory). It's pretty straightforward to implement them yourself, though.
    on the topic of compact, in divide usually DIV and MOD come for free, so a function form of

    DivideAbyB = Div_Mod_int32(A,B,CommonRem);

    returns A/B and also places remainder in CommonRem, a library or global variable.

    The _UDIVSI function already returns both quotient and remainder, you just have to declare it to call it directly (for some reason the compiler isn't merging the calls to divide and modulo, although we've told it that both call the same function). For example you can do:
    typedef struct { unsigned int quot, remainder; } Mydiv;
    
    extern Mydiv _UDIVSI(unsigned int a, unsigned int b) __attribute__((native));
    ...
    Mydiv result = _UDIVSI(x, y);
    // now result.quot is x/y, and result.remainder is x%y
    
    The "__attribute__((native))" says that the function is in COG memory and should be called with the standard COG call/ret sequence instead of the default C calling convention (which is different because C functions can be recursive).
  • Blake Koch wrote: »
    I would like to read an ADC 0831 chip using C Simple IED. Im having trouble finding the code need to pulse the CLK pin as well as the Code needed to return and store the data from DO pin.

    Can anyone help ?

    Thanks
    Blake

    Did you find the code?
  • Every time I see a Spin program translated to C I throw up in my mouth a little bit; Spin is so much more elegant in my mind. That said -- and before the flames get too high -- I will endeavor this year to learn C for the Propeller, and then port my library of objects (about 120 or so -- most not posted). I translate C code to Spin several times a week so there should be no real drama, once I get past my distaste for C, in making everything work.
  • JonnyMac wrote: »
    Every time I see a Spin program translated to C I throw up in my mouth a little bit; Spin is so much more elegant in my mind. That said -- and before the flames get too high -- I will endeavor this year to learn C for the Propeller, and then port my library of objects (about 120 or so -- most not posted). I translate C code to Spin several times a week so there should be no real drama, once I get past my distaste for C, in making everything work.

    Have you considered using basic C++ rather than C, since then you have access to the same basic OO principles that Spin provides?

    @Blake

    I took a couple seconds to review the datasheet for the ADC 0831. It mentioned "TI Microwire" for the serial interface and I believe that basically means SPI right? If that's the case, you can start with PropWare's PropWare::SPI class if you're willing to use a bit of C++ in your project. It will save you the trouble having to bit-bang the serial protocol yourself by providing easy, high-level send and receive functions.

    Check out the API here which lists out all of the functions and, if it sounds good, i'll provide you a zip with all of the files you need to import into SimpleIDE.
  • To me, simplicity is elegance, which is why I like Spin so much. I will attempt to port my programs to straight C (for the Propeller) without using any of the standard libraries (I'll use my own). I don't like the "I can do everything with this one module" approach. Maybe I'm old, but it just seems to lead to bloatware -- which is fine for a PC platform with lots of resources, but not for a small micro.

    BTW... my commentary is not an indictment of your libraries. Though I may never use them myself, I appreciate that you're providing code for Propeller users -- something I try to do via my Spin projects.
  • JonnyMac wrote: »
    To me, simplicity is elegance, which is why I like Spin so much. I will attempt to port my programs to straight C (for the Propeller) without using any of the standard libraries (I'll use my own). I don't like the "I can do everything with this one module" approach. Maybe I'm old, but it just seems to lead to bloatware -- which is fine for a PC platform with lots of resources, but not for a small micro.

    BTW... my commentary is not an indictment of your libraries. Though I may never use them myself, I appreciate that you're providing code for Propeller users -- something I try to do via my Spin projects.
    Ah, I certainly didn't mean to imply you use PropWare or libstdc++. Simply C++ as a language, with proper classes and objects.
  • JonnyMac wrote: »
    Every time I see a Spin program translated to C I throw up in my mouth a little bit; Spin is so much more elegant in my mind. That said -- and before the flames get too high -- I will endeavor this year to learn C for the Propeller, and then port my library of objects (about 120 or so -- most not posted). I translate C code to Spin several times a week so there should be no real drama, once I get past my distaste for C, in making everything work.

    You could always use spin2cpp for the translation from Spin back to C or C++.

    If you prefer to hand-write the C code, you can embed it in special comments in your Spin driver and then have spin2cpp extract the C code (translating the PASM to a C binary blob, and leaving the Spin alone). That's one of the major use cases I imagined for spin2cpp; using the same driver source for Spin and C/C++.
  • Here's the code, it needs no extra libraries, you can add the pin assignments and everything else you need to it, this is all I have right at the moment, it works enjoy! : ]
    /*ADC0831 by electron spectrum*/
    #include "simpletools.h"                      // Include simple tools
    
    int main()                                    // Main function
    { 
      while(1)
      {
        low(1);
        low(0);
        pulse_out(1, 210);
        int adcBits = shift_in(2, 1, MSBPOST, 8);
        high(0);
        putChar(HOME);
        print("Binary   = %b\n", adcBits);
        print("Decimal  = %d\n", adcBits);
        print("Volts +- = %f\n", adcBits*0.019607);
        pause(50);
      }  
    }
    
    960 x 540 - 109K
  • JonnyMacJonnyMac Posts: 9,105
    edited 2016-01-08 21:41
    Using a translation program would in fact defeat my desire to learn C/C++ (to code natively, that is -- I understand C well enough to translate code to Spin and do so frequently). There will be some who are less interested in the process of learning that I who will benefit from your project. Not me; I'm an nut about code with my name on it -- it must be MY code.
  • How featured is C for the Prop?
    struct and union supported?
    typedef supported?

    I learned C in the last 6month and it's not bad once you get a hang of it.
    IAR compiles really tight code when you use High Optimized setting, that rivals any assembly coder.
  • dgatelydgately Posts: 1,630
    edited 2016-01-09 00:26
    tonyp12 wrote: »
    How featured is C for the Prop?
    struct and union supported?
    typedef supported?

    PropGcc is a version of gcc, which means it has all the standard C & C++ features. You are only limited by several of C's standard libraries being large (for the P1's storage capabilities) and so the PropGcc developers have added a few slimmed-down replacements for things like printf and its cousins...

    Basically, you should have little issue in developing typical C or C++ code on the Propeller. It's when you want to code Propeller/microcontroller-specific type actions that you need to think outside the standard C box. SimpleIDE & PropWare as 2 examples, provide many libraries that are specific to supporting the Propeller.


    Just my $.02 US,
    dgately
Sign In or Register to comment.