--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to the Google Groups "BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
OK, so while the executable is running. How much CPU is being used ? The reason I ask may be less than obvious, but I'm asking because I do not know what type pruIo *is*. But the assignment of this type looks remarkably similar to mmap(). e.g. a file mapped to a region in memory.
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
void read_adc(int fd)
{
       char adc[5] = {0};
       int len = read(fd, adc, sizeof(adc - 1));
       adc[len] ='\0';
       printf("%s ", adc);
}
int main()
{
       const char *fname = "/sys/bus/iio/devices/iio:device0/in_voltage0_raw";
       int count = 0;
       while( count++ <= 1000){
               int fd = open(fname, O_CREAT | O_RDONLY);
               if(fd == -1){
                       printf("error: %s\n", strerror(errno));
                       exit(1);
               }
               if(count % 15 == 0 && count != 0)
                       printf("\n");
               read_adc(fd);
               close(fd);
       }
       printf("\n");
       return 0;
}
Amazing, i m awed by your rigorous treatment of the topic :-) and as you said I ran a test of that program, which proved that you are correct!! the program ( mine one) is taking 10.2% to 11% of CPU!! which proves that its in blocking mode.
Â
Non blocking, reads, sees nothing, and then continues execution. So for example if you have two reads back to back on two different channels, it would not matter in what order the data was ready. The first channel to have data would very likely "display" that data first. But in blocking mode. EVERY read after the current read has to wait until it is successful.
But if that is the case, than data would come randomly to me!! 2nd channel 1st and than maybe 4th channel, dont you think its risky? specially in my case, I want to analyze the data, filter it if required & reconstruct the waveform!! :-) your explanation is scaring me :-p
I can SEE that drive!! :-)
Oh, I probably forgot the most important part. Never stop learning. For me I love learning, maybe even more than actually getting anything done heh.
--
void read_adc(int fd)
{
       char adc[5] = {0};
       int len = read(fd, adc, sizeof(adc - 1));
       adc[len] ='\0';
       printf("%s ", adc);
}
In order to reach 20 kHz sampling rate you have to do
Either have a look at the triggers example (to use MM mode) or check out the following code (comming from an example named rb_file for next libpruio versions)
/** \file rb_file.c
\brief Example: fetch ADC samples in a ring buffer and save to file.
Â
This file contains an example on how to use the ring buffer mode of
libpruio. A fixed step mask of AIN-0, AIN-1 and AIN-2 get configured
for maximum speed, sampled in to the ring buffer and from there saved
as raw data to some files.
Â
Licence: GPLv3
Â
Copyright 2014-2015 by Thomas{ dOt ]Freiherr[ At ]gmx[ DoT }net
Â
Thanks for C code translation: Nils Kohrs <nils[ dot ]kohrs{ AT }gmail[ dOt ]com>
Â
Compile by: `gcc -Wall -o rb_file rb_file.c -lpruio -lprussdrv`
Â
\since 0.2.0.2
*/
Â
#include "unistd.h"
#include "time.h"
#include "stdio.h"
#include "../c_include/pruio.h"
Â
//! The main function.
int main(int argc, char **argv)
{
 const uint32 tSamp = 123401;  //!< The number of samples in the files (per step).
 const uint32 tmr = 5000;    //!< The sampling rate in ns (5000 -> 200 kHz).
 const uint32 NoStep = 3;    //!< The number of active steps (must match setStep calls and mask).
 const uint32 NoFile = 2;    //!< The number of files to write.
 const char *NamFil = "output.%u"; //!< The output file names.
 struct timespec mSec;
 mSec.tv_nsec=1000000;
 pruIo *io = pruio_new(PRUIO_DEF_ACTIVE, 0x98, 0, 1); //! create new driver
 if (io->Errr){
        printf("constructor failed (%s)\n", io->Errr); return 1;}
Â
 do {
  if (pruio_adc_setStep(io, 9, 0, 0, 0, 0)){ //      step 9, AIN-0
    printf("step 9 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,10, 1, 0, 0, 0)){ //     step 10, AIN-1
    printf("step 10 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,11, 2, 0, 0, 0)){ //     step 11, AIN-2
    printf("step 11 configuration failed: (%s)\n", io->Errr); break;}
Â
  uint32 mask = 7 << 9;     //!< The active steps (9 to 11).
  uint32 tInd = tSamp * NoStep; //!< The maximum total index.
  uint32 half = ((io->ESize >> 2) / NoStep) * NoStep; //!< The maximum index of the half ring buffer.
Â
  if (half > tInd){ half = tInd;}  //    adapt size for small files
  uint32 samp = (half << 1) / NoStep; //!< The number of samples (per step).
Â
  if (pruio_config(io, samp, mask, tmr, 0)){ //    configure driver
            printf("config failed (%s)\n", io->Errr); break;}
Â
  if (pruio_rb_start(io)){
           printf("rb_start failed (%s)\n", io->Errr); break;}
Â
  uint16 *p0 = io->Adc->Value;  //!< A pointer to the start of the ring buffer.
  uint16 *p1 = p0 + half;    //!< A pointer to the middle of the ring buffer.
  uint32 n;  //!< File counter.
  char fName[20];
  for(n = 0; n < NoFile; n++){
   sprintf(fName, NamFil, n);
   printf("Creating file %s\n", fName);
   FILE *oFile = fopen(fName, "wb");
   uint32 i = 0;        //!< Start index.
   while(i < tInd){
    i += half;
    if(i > tInd){       // fetch the rest(no complete chunk)
     uint32 rest = tInd + half - i;
     uint32 iEnd = p1 >= p0 ? rest : rest + half;
     while(io->DRam[0] < iEnd) nanosleep(&mSec, NULL);
     printf("  writing samples %u-%u\n", tInd -rest, tInd-1);
     fwrite(p0, sizeof(uint16), rest, oFile);
     uint16 *swap = p0;
     p0 = p1;
     p1 = swap;
    }
    if(p1 > p0) while(io->DRam[0] < half) nanosleep(&mSec, NULL);
    else     while(io->DRam[0] > half) nanosleep(&mSec, NULL);
    printf("  writing samples %u-%u\n", i-half, i-1);
    fwrite(p0, sizeof(uint16), half, oFile);
    uint16 *swap = p0;
    p0 = p1;
    p1 = swap;
   }
   fclose(oFile);
   printf("Finished file %s\n", fName);
  }
 } while(0);
 pruio_destroy(io);
 return 0;
}
rb_file {#SubSecExaRbFile}
-------
\Item{Description}
 This file contains an example on how to use the ring buffer mode of
 libpruio. A fixed step mask of AIN-0, AIN-1 and AIN-2 get configured
 for maximum speed, sampled in to the ring buffer and from there saved
 as raw data to some files.
\Item{Preparation}
 No preparation is required. Optionaly you can customize the number of
 samples, the sampling rate or the number of samples in the source
 code and recompile your version.
\Item{Operation}
 Start the program by `./rb_file` and you'll see console output like
~~~{.txt}
Creating file output.0
 writing samples 0-65534
 writing samples 65535-131069
 writing samples 131070-196604
 writing samples 196605-262139
 writing samples 262140-327674
 writing samples 327675-370202
Finished file output.0
Creating file output.1
 writing samples 0-65534
 writing samples 65535-131069
 writing samples 131070-196604
 writing samples 196605-262139
 writing samples 262140-327674
 writing samples 327675-370202
Finished file output.1
~~~
 The program created two new files in the current folder, named
 output.0 and output.1. The files contain the raw data from the three
 ADC channels AIN-0 to AIN-2.
\Item{Source Code}
 src/examples/rb_file.bas
 src/c_examples/rb_file.c
BR
pruio_new(PRUIO_DEF_ACTIVE, 0, 0, 0)pruio_config(io, 1, PRUIO_DEF_STPMSK , 0, 4)So, is my configuration is wrong or the approach?
Sorry if my queries sound novice but I am new to this & I am felling overwhelmed by the whole thing..!! :-)
I have been reading the processor TRM and PRU reference manual and I petrified, its kind of ocean of information. ( it remind me of "The old man & the sea"!! )
Sincerely,
Rathin
PS:
--
...
Dear Wulf man,
Thanks for the input. So do you recommend that external ADC and communicate through PRU with SPI, GPIO?
and do you have some good ADC IC in mind?
Well, second things is you mean to say if I use 8 ADCs I cant achieve 1.25Khz+ sample rate, Than should I use external ADC? would it be easier?
and to be frank I have plenty of doubts in the pruio construct and pruio_config, I which are as follows:
- You said I have 183 cycle open delay - but where is it? I have made everything 0 ( zero!!) you can have a look at option setting in line bellow!!
pruio_new(PRUIO_DEF_ACTIVE, 0, 0, 0)
- And in my pruio_config, I have made averaging to 0 (you can see that as well). delay 0,
pruio_config(io, 1, PRUIO_DEF_STPMSK , 0, 4)
So, is my configuration is wrong or the approach?
few queries with respect to your new example
- This is also for only 3 ADC channels, so if I extend it for 8, will this one also become slow?
There is only one ADC in the sitara processor.
There is a 8 to 1 mux to provide you with 8 inputs.
- I am going to "monitor" the inputs continuously, so I require continuous stream of input, will this approach work?
- Its later part of my project but I saw u using system timer so asking that I also want to time stamp the data with system time, so can it be done here or should I do it later?
I also do not feel that the whole library is open enough. Last I looked, one had to download a pre-compiled binary in order to make it work. This is not open source, which is big on many peoples mind.
It is my personal opinion that the documentation for libpruio could use *A LOT* of work.
--
Dear Community Members,
I am trying to implement a fast 8 channel Analog capture using on board ADC on BBB. I know there are only 7 available on pin header, but as I am starting off & learning I am ok with count of 7. :)
I just wanted to have an opinion about the approach to opt for, What would be the most optimum (& preferably faster to implement) option to achieve it?
I have read quite a few articles and thread (& more confused ) and currently I am using libpruio for implementing it but as of now even after configuring libpruio I am only getting 900 - 1000 samples per seconds.
So, is it my configuration wrong or for such high speed I should opt for external ADC? or something else?
I am completely NEW to EMBEDDED domain. So please pardon me.
It would be great if someone could guide me, precisely towards some direction.
Sincerely,
Rathin
--
So yeah, I will try out your steps and let you know, but I have one assignment hence bit stuck with it.. please give me a day to try out...
I never even saw a PDF . . .
On Tue, Nov 11, 2014 at 1:09 PM, ... <...> wrote:
--
Hi TJF,
I had a small gap so I tried your new code, and Its giving me "config fault: sample rate too big".
I tried changing tSamp, to 2000 but still it doesn't work So what changes should I make?
 const uint32 tmr = 50000;    //!< The sampling rate in ns (50000 -> 20 kHz).
  IF Samp < 2 THEN ' IO mode
   Samples = 1
   TimerVal = 0
  ELSE
   IF r < 1 THEN       .Errr = @"no step active" : RETURN .Errr
   Samples = Samp * ChAz
   IF (Samples SHL 1) > .ESize THEN _
                 .Errr = @"out of memory" : RETURN .Errr
   d = (d * (Conf->ADC_CLKDIV + 1) * 1000) \ 24
   IF Tmr <= d ORELSE Tmr < 5000 THEN _
              .Errr = @"sample rate too big" : RETURN .Errr
   Value = .ERam
   TimerVal = Tmr
  END IF
Then compile and install the new version.and one another query how to extend the same code of 8 ADCs? just to change NoStep??
 const uint32 NoStep = 3;    //!< The number of active steps (must match setStep calls and mask). const uint32 NoStep = 8;    //!< The number of active steps (must match setStep calls and mask).
...
  if (pruio_adc_setStep(io, 9, 0, 0, 0, 0)){ //      step 9, AIN-0
    printf("step 9 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,10, 1, 0, 0, 0)){ //     step 10, AIN-1
    printf("step 10 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,11, 2, 0, 0, 0)){ //     step 11, AIN-2
    printf("step 11 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,12, 3, 0, 0, 0)){ //     step 12, AIN-3
    printf("step 12 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,13, 4, 0, 0, 0)){ //     step 13, AIN-4
    printf("step 13 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,14, 5, 0, 0, 0)){ //     step 14, AIN-5
    printf("step 14 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,15, 6, 0, 0, 0)){ //     step 15, AIN-6
    printf("step 15 configuration failed: (%s)\n", io->Errr); break;}
  if (pruio_adc_setStep(io,16, 7, 0, 0, 0)){ //     step 16, AIN-7
    printf("step 16 configuration failed: (%s)\n", io->Errr); break;}
  uint32 mask = 255 << 9;     //!< The active steps (9 to 16).
...
1) This program samples only 1 ADC correct? involtage0_raw To extend it for all 7 channels woudl I have to create 7 such pointers, correct?
2) this is Ti rt kernel, is it same as TI-RTOS? and if not, where can I find it's APIs?
3) This kernel has completely new structure, so now my PRUs are completely unusable :-) any suggestions? initially it was accessible by "/sys/devices/bone_capemgr.*/slots" which now doesn't exist!!
4) Is your existing code able to reach 3K sample speed? if not can you suggest changes for that?
if(len == -1){Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â close(fd);Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â continue;Â Â Â Â Â Â Â Â Â Â Â Â Â
}
Hi TJF,
... but they are binaries!! I am not able to read them with any format or in any text-editor. Can you suggest how to read them?
--
#include<stdio.h>
int main()
{
  FILE *fp = NULL;
  short result[100];
  int i;
  fp=fopen("output.0", "w+");
    rewind(fp);
  if(fp != NULL)
  {
    fread(result, sizeof(short), 100 /*# of samples*/, fp);
  }
  else
    return 1;
  printf("Result\n");
  for (i = 0; i < 100; i++)
    printf("%d = %d\n", i, (int)result[i]);
  fclose(fp);
  return 0;
}
4) I tried with while(1) and it ran perfectly. Now I will try changing to continuous mode as well as the no of ADC in to the program and will report back to you..!!Â
Thanks for the kick start, It is of immense help and yes I have understood since the beginning that Google is our BEST friend when working on something new...!! though my results are not as accurate as ur's but working on it.. :-)
Once again thanks.. will post back my new code, soon.
This driver is based on the IIO (Industrial I/O subsystem), however this is the first release of this driver and it has limited functionality:
http://processors.wiki.ti.com/index.php/AM335x_ADC_Driver's_Guide
http://processors.wiki.ti.com/index.php/AM335x_ADC_Driver's_Guide
[listing severe limitations of the ADC driver]
Dear TJF,
Sorry to bug you with a silly question, I thought being a binary it must have some specific encoding rel. to library hence I asked it. I didnt knew it was lack of knowledge. I am sorry...!!
I Have figured out the way to read binary (code pasted bellow for others;) but I have a doubt in it that I have lot of Zeros & negative readings as well
Is it because of my decoding error or is it the samples themselves missing.
unsigned short result[100];
Here's code I use (FB syntax):
VAR fnam = "output.0", fnr = FREEFILE
IF OPEN(fnam FOR INPUT AS fnr) THEN
 ?"Cannot open " & fnam
ELSE
 DIM AS USHORT v
 VAR cc = 8, c = 0, i = 0
 WHILE NOT EOF(fnr)
   c -= 1 : IF c <= 0 THEN i += 1 : c = cc : ? : ? i & ": ";
   GET #fnr, , v
   ? v,
 WEND
 CLOSE #fnr
END IF
--
Have you experimented with buffer size? is there any optimal value calculation? Would it have any impact on the result, Like if we keep a larger buffer and than directly take that buffer that way it would be faster? I have currently kept 1k.
You're working with two things, FIFO and ADC.
What does the ADC do when the FIFO is full?
What does the FIFO do when it is full?
How do you know?
Do you record it?
Well, I'd guess something like this:Â the FIFO data is stored on the
heap, which is malloc'd. You need the pointers as needed to figure
out where it is.  Standard pointers to head and tail of the ring
buffer will be stored locally, unless someone did a pointer to the
data structure of the FIFO (but not the data itself). I'm doing that
in an OS that I'm writing. The only advantage here is that heap
memory (or managed memory) is managed by the OS, and should not belong
to any one task. (you could argue that, but it's more convenient this
way for me.)
You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/OXe88RyHqX8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
no longer returns any value or doesn't return a value you expect? You
should be able to read the memory regardless. What it says is another
matter.
Just offhand, I'd suggest not messing with the hardware directly, but
using the system drivers unless you want to write system level
drivers.
Guess there isn't a linux ADC driver for this chip. I'm used to
writing bare metal drivers myself, but not for linux at all.
The heap memory is effectively the *remaining* memory that the
operating system doesn't use, it should include all of the data
segments, the ram data, and the current stack. From this, malloc
pulls memory, (in the GCC-AVR) from the bottom up.
So it doesn't at all seem to be the same as the "mem" array, or the
"port" array...
I m just sitting here astonished & awed by the discussion!! Congratulations on success..! :-)Take away from this discussion for me is that, I have a long way to go!
RathinJust know that no one is born knowing any of this, or anything for that matter. We all have to start from square one - as it were. As far as learning C, or any programming language, that just comes with lots of code writing. The more you write, the more you fail, and hopefully learn from. I do think it is important to emphasize the key point: That failure in this context is not a bad thing. So long as you eventually learn *why* something failed. Hopefully in many cases, sooner rather than later.