adc periodic framework using both adc0, and 1, and their timing between them

Dear Forum,

 

I have a few questions about the configuration and use the of the periodic framework for the adc.  I am needing to setup and run both adc's at the same time.  From the looks of it and from a few trials it seems like you can only setup one framework for a specific adc.  What Im hoping to do is to be able to have some adc start signal start both adc at the same time.  Is there a way to do this?  Can this also be done with the sample and hold circuitry enabled?  Basically Im needing to capture 6 channels all at the same time. 

Second question is with the configuration, of the "length of data-buffer" in the properties of the periodic framework.  I have 4 channels Im sampling, and have 100 sampling iterations, that will produce 400 sample registers that will be filled.  But when I set that up and run  I get the BSP_CFG_HANDLE_UNRECOVERABLE_ERROR (0); withing the void g_sf_adc_periodic0_err_callback_internal(void * p_instance, void * p_data).  Since I have this setup as 12 bit samples, Im guessing these are all stored as 16bit unsigned ints.  Not 32 bit.  So then is the "length of data-buffer" a size defined as 8 bits or is it actually 16 bit for data space.  It acts like its 8 bit, cause if I increase the size in the above example from 400 to 800 it works just fine.  Or is it that you cant have "length of data-buffer" equal to the exact number of storage locations required.    

Third thing I noticed as I was testing out the adc's was cross talk.  I saw at most 20 bits of cross talk.  My test setup was simply 8 pots, connected between 3.3v and ground on a SK board plugged into the j20 connector.  The wipers of the pots were fed back into ADC000-003, and ADC100-103.  Basically the first 4 channels of each adc.  Im thinking this must be simply a setup or some kind of code issue.  But the cross talk should in no way be this bad right?  I could find no reference to cross talk in the user manual ver 1.2 from aug 2016.  Is it maybe called something different? 

Thank You
Matt

Parents
  • Hi Matt!
    For the first question - I'm affraid that SSP doesn't support multiple ADC units under single framework. The workaround would de overriding the ADC Preiodic Framework function APIs to adjust them to your needs or develop your own ADC periodic scan driver.

    2nd question - The init function returns SSP_ERR_INSUFFICIENT_SPACE if number_adc_of_channels_used * sample_count * 2 > length_of_data_buffer

    3rd question - Just to clarify... What do you mean by "20 bits of cross talk"? You mean that one channel affects other so the reading changes by 20, right?

    KR, Jakub
  • Thank you Jakub!

    For multiple adc units, could I just add another framework?  Or in my case needing to fire all the adcs at the same time would it simply be better to go in and do my own framework code?

    Ah that was what I was kind of thinking but had not seen a formula for the length_of_data_buffer.  So the *2 is what I was missing.  

    Yes Im seeing upto 20 counts of cross talk from the input on one adc to the input on another.  Basically when I have one adc own to zero volts on the input and I set the one next to it, or even a few over Im seeing at least 20 counts.  I think yesterday afternoon I was seeing even a few more then that.  I sure hope this is not a hardware issue and maybe has more to do with how the framework code is switching the muxing internally.  Im guessing there is a settling time on the muxes that is not being met by the current framework code.  Im sure thinking this has to be a software setup/usage thing in the framework code somewhere.  I cant imagine that something like this got missed by the factory guys.  Its just way to many counts.     

     

    Attached is what the daughter board looks like that I attached to the SK board for simple testing out of the adc's.  I just drew on the SK schematic how the pots hookup.  Power and ground Im using from the connector. 

    Thanks again Jakub!

    Matt

  • Hi Jakub,

    What is also interesting in the setup for length_of_data_buffer, when I do that and set the memory space to 2x it looks like the upper half of that memory is not being filled with the callback.  Each time the call back runs, only the lower portion of the memory is updated.  See below.

    Thanks

    Matt

  • Oh that second image somehow over wrote the first.  He is the correct first image.

  • Hi Jakub and forum,

    Ok, After more experimentation I can say Im constantly seeing cross talk. I have only tested in combinations of the the first 4 and 7 channel combinations. 0-3, 0-6 on a s7g2-sk board using adc unit 0. I only have pots wired to Ch0-3 as shown in the schematic above. All other input are as they are wired on the board. I test by applying 3.3 volts to each adc input through the pot, one by one leaving the other inputs at ground. Now one thing I have not tried would be disconnecting and replacing the power that is on the connector J20 (+3V3) and switching over to the analog power(+3V3ANA) from the board. Looks to be available on the Arduino shield connector j24.8 after R115 is populated with a zero ohm resistor. Ill try this tomorrow. But when running on the main power the results are below.

    When looking at Ch0-3
    Ch0 reading 4095 puts 22 counts on Ch1
    Ch1 reading 4095 puts 22 counts on Ch2
    Ch2 reading 4095 does not seem to effect its neighbors.
    Ch3 reading 4095 puts 22 counts on Ch0
    When not in use the above channels were pulled to ground and not left floating.

    When looking at Ch0-6
    Ch0 reading 4095 puts 22 counts on Ch1
    Ch1 reading 4095 puts 22 counts on Ch2
    Ch2 reading 4095 does not seem to effect its neighbors.
    Ch3 reading 4096 puts ch4->3647, ch5->3368,ch6->3176 (when at 0v on ch3 ch4->366,ch5->717,ch6->834)

    Has anyone else see any adc cross talk issues? Any of you Renesas folks seen anything like this? More importantly, does anyone have any ideas on how to fix this or is this actually with in the performance spec?

    With respect to the The init function returns SSP_ERR_INSUFFICIENT_SPACE error. Yes, if you specify # of channels* counts*2 it will not produce the error. However it will also not run properly. You need to add +1 to that calculation for memory space. If you dont, you will see like what is shown in the above image. Half the memory space is used the upper half is left unused. The ssp1.2.0 user manual describes this in section 6.2.1.1 but does not specify that you need +1 more storage locations to get it filled and used properly. I think its assumed one may specify several times that space required. Running at the minimum does not appear to work.

    Thank for any help!
    Matt
  • Hi Matt!
    I have tried to investigate the problem. I have noticed the cross talk on SK-S7G2 and DK-S7G2 (haven't tried other boards). For now I don't see any solution to fix that and also haven't seen any notice in the documentation. On the other hand, the cross talk is about 0.5% of the resolution, for some of the applications this might be negligible...

    Speaking about user buffer capacity - I have also noticed that. My advice for now is to leave a space for one extra sample in the buffer...
    KR, Jakub

  • Hello Matt,

    You may observe cross-talk if the sample time is not sufficiently long - scan result for previous channel will affect the current one. You should modify A/D Sampling State register (ADSSTRn) to accommodate for that. From Section 46.3.6 of the S7G2 User's Manual:

    The A/D conversion processing time (tCONV) consists of the input sampling time (tSPL) and time for conversion by
    successive approximation (tSAM). The sampling time (tSPL) is used to charge sample-and-hold circuits in the ADC12. If
    there is not sufficient sampling time because of the high impedance of an analog input signal source, or if the A/D
    conversion clock (ADCLK) is slow, sampling time can be adjusted using the ADSSTR register.

    You should also investigate section 46.3.9: Disconnection Detection Assist Function, to fix the charge for sampling capacitance.

    These features are not implemented at the driver level, so they'll need to be configured using register access (R_S12ADC0 and R_S12ADC1).

    Regards
  • Hi Karol and Jakub,

    Thank you both!!

    Karol, That was it. The stock configuration the driver puts in there looked like it might have been the delay needed for the 10bit converter, not the 12. Its to bad in the driver that is not a configurable setting or at least its to bad it does not set that value to what the datasheet says is needed for a delay based upon what is chosen as far as how many bits the converter is doing. I have plenty of drive current as Im testing this setup, so Im going to keep the Disconnection detection assistant at the stock config for right now. But if my end drive circuitry changes that Ill make changes to it.

    As far as accessing the values in the ADC for the ADSSTR. Below is the code I used, but is there a better way to do this? Ill be honest I struggled a little to get this to work. Having to pass the pointer to g_adc_sample_state was a bit confusing. I was hoping I could just call the register and set it = x. So as far as timing goes, I think the manual said the delay required for 12bits was 13 adc clocks. I found about 5 counts of cross talk going from 11 to 13, and then out at 18 the cross talk was not detectable. Other then slowing down the maximum samples per second the adc's can make, is there any issues that you are aware of by extending that time out?

    Again thank you for the help, and I hope you both have great weekend!

    Matt

    // Define a configuration structure used in the API call.
    adc_sample_state_t g_adc_sample_state =
    {
    .reg_id = ADC_SAMPLE_STATE_CHANNEL_0,
    .num_states = 0x12
    } ;

    // Set the sample state count for the channel
    // ssp_err = R_ADC_SetSampleStateCount (&adc_ctrl, &g_adc_sample_state);
    g_adc0.p_api->sampleStateCountSet(g_adc0.p_ctrl,&g_adc_sample_state);

    g_adc_sample_state.reg_id = ADC_SAMPLE_STATE_CHANNEL_1;
    g_adc0.p_api->sampleStateCountSet(g_adc0.p_ctrl,&g_adc_sample_state);
    g_adc_sample_state.reg_id = ADC_SAMPLE_STATE_CHANNEL_2;
    g_adc0.p_api->sampleStateCountSet(g_adc0.p_ctrl,&g_adc_sample_state);
    g_adc_sample_state.reg_id = ADC_SAMPLE_STATE_CHANNEL_3;
    g_adc0.p_api->sampleStateCountSet(g_adc0.p_ctrl,&g_adc_sample_state);
    g_adc_sample_state.reg_id = ADC_SAMPLE_STATE_CHANNEL_4;
    g_adc0.p_api->sampleStateCountSet(g_adc0.p_ctrl,&g_adc_sample_state);
  • Hello Matt,

    I'm glad to see that you've managed to solve your problem. The APIs you used are the best way to set sample states. I believe the structure was used instead of 2 arguments in order to help you define an array of sample states, e.g:
    adc_sample_state_t adc_sample_states[] = {
    {
    .reg_id = ADC_SAMPLE_STATE_CHANNEL_0,
    .num_states = 0x12
    } ,
    {
    .reg_id = ADC_SAMPLE_STATE_CHANNEL_1,
    .num_states = 0x11
    } ,
    {
    .reg_id = ADC_SAMPLE_STATE_CHANNEL_4,
    .num_states = 0x0F
    }
    };

    Which can then be applied using a simple loop.

    Regards
  • Hi Karol,

    Ok. I figured there had to be a reason why it was setup like that. Thank you again for the help!

    Matt
  • Hello Karol,

    I have question with respect to the Length of data-buffer. I need 8 adc input. So Im using the first 7 and then #19. These were setup in the driver under the periodic framework. When I go and define the length of data-buffer I need to define at least 40 so that I do get errors. There are 12 memory locations that are then required but not used. Lots of wasted space. Is there a way with the the periodic framework to not need the extra unused space between 7 and 19 on the adc channels? Im thinking that dtc is not able to do anything other then a linear memory space move and cant do just the used memory space. Is that correct or is there a way to do it with out wasting the space?

    Thanks
    Matt

  • Hello Matt,

    I'm afraid this won't be possible with periodic ADC Framework. For any channel sequence, the framework would select a vector of channels starting at the lowest one and ending at the highest one. These register addresses will then be used as a source for data transfer into Framework-defined buffer. If the sequence was non-continuous, multiple transfers would be required.

    Depending on how often you're sampling the data, it may be better idea to use driver only. When configured in continuous mode, at any point in your application you can call read to retrieve the latest reading from ADC registers. Pairing this up with the dedicated thread to capture readings periodically will result in a reasonably simple, yet efficient, solution.

    Regards
Reply
  • Hello Matt,

    I'm afraid this won't be possible with periodic ADC Framework. For any channel sequence, the framework would select a vector of channels starting at the lowest one and ending at the highest one. These register addresses will then be used as a source for data transfer into Framework-defined buffer. If the sequence was non-continuous, multiple transfers would be required.

    Depending on how often you're sampling the data, it may be better idea to use driver only. When configured in continuous mode, at any point in your application you can call read to retrieve the latest reading from ADC registers. Pairing this up with the dedicated thread to capture readings periodically will result in a reasonably simple, yet efficient, solution.

    Regards
Children
  • Hello Karol,
    Yeah I was afraid that might be the case. Sample rate is currently at 1ksps for each 8 channels. In this application I think that rate is just fine and might be able to be decreased. Though I have another application where Ill need that to be on order of 3 to 5 times faster.

    Karol Thank you for the input and response.

    Matt