Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 20 of 20

Thread: Pulses counting in intervals with teensy 3.2

  1. #1
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11

    Pulses counting in intervals with teensy 3.2

    Hello everyone!
    I’m trying to use the teensy 3.2 with PaulStoffregen’s library (https://github.com/PaulStoffregen/FreqCount) to count the number of partial discharges.

    Code:
    #include <FreqCount.h>
    #include <LiquidCrystal.h>
    const int rs = 12, en = 11, d4 = 9, d5 = 8, d6 = 7, d7 = 6;
    LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
    
    unsigned long count = 0;
    unsigned long prior_count=0;
    
    void setup() {
      FreqCount.begin(100);
      display.setBrightness(0x0F);
      lcd.begin(16, 2);
      lcd.print("PULSES:");
    }
    
    void loop() {
      if (FreqCount.available()) {
        count = count + FreqCount.read();
        if (count != prior_count) {
          Serial.println(count);
          
          lcd.setCursor(0, 1);
          lcd.print(count);
          
          prior_count = count;
        }
      }
    }
    Example signal (frequency not higher than 300 kHz):

    Click image for larger version. 

Name:	example.png 
Views:	40 
Size:	7.4 KB 
ID:	20114

    The problem is, that the amplitude of the signal is very low (about 100-200 mV), so the Teensy doesn’t count it.

    I want the teensy to count the signals in some kind of ‘intervals/periods’ (not longer than 0,02 s) in which counted will be only peaks with an amplitude more than the trigger (set on 100 mV for example). And if in this period the teensy find 1 or more peaks higher than a trigger level, it should mark is as a ‘positive’ and add one to the counted pulses.

    It is possible to do it with this library?

  2. #2
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,600
    That’s not the purpose of the freqcount library which expects clean logic levels. To count your signal, you’d have to add some external circuitry, for example around a LM331 comparator where you could add a multi turn potentiometer to set a trigger level.

  3. #3
    Deleted User
    Guest
    With this signal you get a large spectrum of pulse widths. The question is, what kind of information do you expect and want to get out of this.

    I'd program that "by hand":
    digitize the signal into a buffer
    scan through the data for edges
    check if the edge is tall enough to count as useful
    use this data (counting, timing, etc)

    This way you get no artefacts from filtering, etc.
    The built-in ADC has about 630k/sec sample rate, so that should barely work.
    Last edited by Deleted User; 05-15-2020 at 09:07 PM.

  4. #4
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    Quote Originally Posted by Theremingenieur View Post
    That’s not the purpose of the freqcount library which expects clean logic levels. To count your signal, you’d have to add some external circuitry, for example around a LM331 comparator where you could add a multi turn potentiometer to set a trigger level.
    Ok, I thought that this library counts the rising slopes, I'll get rid of this. So you thing that this comparator will be better option, than simply using some kind of analogRead instruction? The next question, I should use it in a voltage-to-frequency circuit? Will it make square signal based on how high it went above the trigger?

    Quote Originally Posted by Deleted User View Post
    With this signal you get a large spectrum of pulse widths. The question is, what kind of information do you expect and want to get out of this.
    The thing is that I only have to recognize changes in the signal, I don't care about the width or duration. As you can see on this example there is a noise (10809 - 11400 sample) and then the discharge begins. I'd like the teensy only to recognize, that the signal went higher than for example 200 mV in this interval, so the counter add one to the number of counts.

    Quote Originally Posted by Deleted User View Post
    I'd program that "by hand":
    digitize the signal into a buffer
    scan through the data for edges
    check if the edge is tall enough to count as useful
    use this data (counting, timing, etc)
    About which kind of a buffer have you thought? Register? Wouldn't it take too much time? Do you have any example codes with that sort of programs?
    As you wrote it, it looks pretty easy but I have no idea how to start it.

  5. #5
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    Maybe, I'll try to summarize the current work status.

    I wrote a PM to Theremingenieur, because when I was doing research on LM331 (F/V converter) which he advised me to use, I realized that he made a mistake. That was right, he thought about the LM311 (comparator).
    Finally, I used it to compare this two signals, but now there is a problem, because comparator is adding some noise when it's changing the state of the output. The counter (teensy with FreqCount library) counts it as hundreds of pulses.

    Click image for larger version. 

Name:	IMG_1402.jpg 
Views:	42 
Size:	127.2 KB 
ID:	20554

    I tried to use some pull-down capacitors on the output (100 pF+100 uF parallel), but they completely slowed down the device, it became completely unresponsive.

    In PM Theremingenieur recommended me also to add some hysteresis to the circuit, which as I understand as adding a resistor between output and non-inverting input, like in this picture? Is there any typical values of resistor like this?

    Click image for larger version. 

Name:	1.JPG 
Views:	35 
Size:	29.5 KB 
ID:	20555
    (https://www.analog.com/en/analog-dia...ysteresis.html)

  6. #6
    Senior Member+ Theremingenieur's Avatar
    Join Date
    Feb 2014
    Location
    Colmar, France
    Posts
    2,600
    All you need to calculate the values for the resistors R1 and R2 are given in the schematic from analog.com. To use these formulae, you have to analyze the input signal first and determine two voltage levels. A lower one which is low enough to identify for sure a true low input level, and a higher one which the input signal must reach to drive the output high. Then, only input peaks which are above VIH will drive the output high and it will remain high until the input signal goes below VIL. As long as the signal will be between VIL and VIH, the comparator will not change its output state. After you found these two values, you set first Vref to (VIH + VIL) / 2. Afterwards you use the given formulae and transform them to solve for R1 and R2, since you have already Vref, VIH, and VIL.
    There aren’t “typical values”, these depend from the input signal and the required “cleaning” of the latter and are thus different for each individual application.

  7. #7
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    The solution of my problems was adding a peak detector circuit before comparator and everything started working very well. Then, the hysteresis became unnecessary.

    Now, I want to improve my device by adding a SD card to register the number of pulses. I also want to add RTC, to write out the time and corresponding pulses (kind of register). Is it possible to connect FreqCount library and SD library in one program? I'm afraid, that external interrupts caused by pulses can lead to problems with writing on SD card, what do you think?

  8. #8
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    Hello! Does anybody find any solution to my problem to connect FreqCount with SD card?

  9. #9
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,552
    Quote Originally Posted by brogue View Post
    Is it possible to connect FreqCount library and SD library in one program?"
    yes.
    Quote Originally Posted by brogue View Post
    I'm afraid, that external interrupts caused by pulses can lead to problems with writing on SD card, what do you think?
    Should work. Its has a clock line.
    Quote Originally Posted by brogue
    Hello! Does anybody find any solution to my problem to connect FreqCount with SD card?

    Have you actually tried to solve the problem yourself?
    What exactly is not working?
    Where is the sourcecode?

  10. #10
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,420
    Quote Originally Posted by brogue View Post
    Hello! Does anybody find any solution to my problem to connect FreqCount with SD card?
    Also note that current TeensyDuino 1.54 Beta is changing the SD code to a more efficient alternate version.

    Would suggest working with that version to see functionality.

    Current Beta is #5 - but refresh to #6 may be coming ... though not sure if that has any changes to the new SD code that is using the SdFat library.

  11. #11
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    Quote Originally Posted by Frank B View Post
    yes.
    Doubt. In Hardware Requirements (https://www.pjrc.com/teensy/td_libs_FreqCount.html) there is an information, that the library requires special pin, Teensy 3.2 - Pin 13.

    Quote Originally Posted by Frank B View Post
    Should work. Its has a clock line.
    Have you actually tried to solve the problem yourself?
    What exactly is not working?
    On the other hand, I have to use the <SD.h> including the <SPI.h> library (some kind of bus, as i read), which is using the following pinout:
    CS to pin 14,
    SCK to pin 13,
    MOSI to the pin 11,
    MISO to pin 12.
    So the thing is, that I have a some kind of the collision between this libraries.

    Quote Originally Posted by Frank B View Post
    Where is the sourcecode?
    The sourcecode doesn't exist. Firstly, I have to manage with the hardware problems.

  12. #12
    Senior Member
    Join Date
    Nov 2015
    Location
    Cold hollow VT
    Posts
    201
    Look at the card that came with your Teensy 3.2. It shows where the pins are located. You will also notice some pins are listed in grey text, they are alternate pin assignments. It appears that all the SPI pins have at least one alternate, maybe more. There are commands to make the alternate pins active. I don't have them in front of me but you could do a web search for something like 'teensy alternate spi pins' and examine the information at the links.

    These are examples of source code in the arduino environment for the bits and pieces to do what you want. You have to mix them together into one program to get your desired results. We can't do that for you, but we can help guide you to figure out what went wrong or provide clues.

    Typical programming for me is the Arduino environment on one screen and an internet browser in the other to find reference material.

  13. #13
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    Thanks for you reply. I found the information about alternative pins for the SPI library. As you can see at https://www.pjrc.com/store/teensy32_card7a_rev3.png. The alternative pin for SCK is the pin 14. Firstly, I decided to go for some basic example code, directly from arduino forum.
    Code:
    #include <SPI.h>
    #include <SD.h>
    File myFile;
    void setup() {
    // Open serial communications and wait for port to open:
    Serial.begin(9600);
    
    
      SPI.setSCK(14); // SCK on pin 14
      SPI.begin();
    
    while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
    }
    Serial.print("Initializing SD card...");
    if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    while (1);
    }
    Serial.println("initialization done.");
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    myFile = SD.open("test.txt", FILE_WRITE);
    // if the file opened okay, write to it:
    if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("This is a test file :)");
    myFile.println("testing 1, 2, 3.");
    for (int i = 0; i < 20; i++) {
    myFile.println(i);
    }
    // close the file:
    myFile.close();
    Serial.println("done.");
    } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
    }
    }
    void loop() {
    // nothing happens after setup
    }
    As you can see, I decided to define the alternative SCK pin as 14 and ...it simply doesn't work. I tried it many times without any solution. And, on the other hand, if I delete line "SPI.setSCK(14)" and move the SCK cable to pin 13, everything works perfect. I think, I might have a problem with my Teensy...? What do you think? I have run out of ideas...

  14. #14
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    298
    I don't know but just a thought, does SPI.setSCK need to go after SPI.begin?

  15. #15
    Senior Member
    Join Date
    Nov 2015
    Location
    Cold hollow VT
    Posts
    201
    @brogue I'm initializing my SPI the same sequence as you are. I don't know how fast the SD card you are using is. Have you tried to slow down the SPI bus for the SD Card by using either

    p3=(!SD.begin(sdCs), SPI_HALF_SPEED);

    OR

    p3 = (!card.init(SPI_HALF_SPEED, sdCs));

    (So many different versions of changing code so try one then the other.)

  16. #16
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    Quote Originally Posted by BriComp View Post
    I don't know but just a thought, does SPI.setSCK need to go after SPI.begin?
    I've tried it, it doesn't change anything. But according to this thread https://forum.pjrc.com/threads/62897...le-SPI-devices it should be okay.

    Quote Originally Posted by grease_lighting View Post
    @brogue I'm initializing my SPI the same sequence as you are. I don't know how fast the SD card you are using is. Have you tried to slow down the SPI bus for the SD Card by using either

    p3=(!SD.begin(sdCs), SPI_HALF_SPEED);

    OR

    p3 = (!card.init(SPI_HALF_SPEED, sdCs));

    (So many different versions of changing code so try one then the other.)
    What's the meaning of the p3? When I added the line, that you've suggested to my code (in void setup()), during the verification, there was a error 'the p3 was not declared'. But in my opinion, everything should work without slowing down the SPI bus - if I connect SCK to pin 13 and delete the line 'SPI.setSCK(14);' everything works fine.

    As I said, I have run out of ideas - maybe there is a mistake in this pinout card (https://www.pjrc.com/teensy/card7a_rev3_web.pdf) and SCK alternative pin isn't 14... I decided to buy Teensy 4.0 with 3 independent SPIs so I will be able to connect to SPI1 and everything should work.

  17. #17
    Senior Member
    Join Date
    Nov 2015
    Location
    Cold hollow VT
    Posts
    201
    Ooops, my bad (lazy copy/paste). I just use p3 to collect the status of the 'begin' or 'init' operations to check the completion results. You could declare it or delete it as it is optional.

    Are you aware that SD has error codes that help determine what went wrong.

  18. #18
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    Okay, I've changed the program to get more information about what is going on with my SD connection. It's copied from here http://mb-raw.blogspot.com/2017/07/t...l-sd-card.html

    Code:
    #include <SD.h>
    #include <SPI.h>
    
    // set up variables using the SD utility library functions:
    Sd2Card card;
    SdVolume volume;
    SdFile root;
    
    const int chipSelect = 10;    
    
    void setup()
    {    
      // Open serial communications and wait for port to open:
      Serial.begin(9600);
      
     SD.begin(chipSelect);
       while (!Serial) {
        ; // wait for serial port to connect. Needed for Leonardo only
      }
    
      Serial.print("\nInitializing SD card...");
    
      // we'll use the initialization code from the utility libraries
      // since we're just testing if the card is working!
      if (!card.init(SPI_HALF_SPEED, chipSelect)) {
        Serial.println("initialization failed. Things to check:");
        Serial.println("* is a card inserted?");
        Serial.println("* is your wiring correct?");
        Serial.println("* did you change the chipSelect pin to match your shield or module?");
        return;
      } else {
       Serial.println("Wiring is correct and a card is present."); 
      }
    
      // print the type of card
      Serial.print("\nCard type: ");
      switch(card.type()) {
        case SD_CARD_TYPE_SD1:
          Serial.println("SD1");
          break;
        case SD_CARD_TYPE_SD2:
          Serial.println("SD2");
          break;
        case SD_CARD_TYPE_SDHC:
          Serial.println("SDHC");
          break;
        default:
          Serial.println("Unknown");
      }
    
      // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
      if (!volume.init(card)) {
        Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
        return;
      }
    
    
      // print the type and size of the first FAT-type volume
      uint32_t volumesize;
      Serial.print("\nVolume type is FAT");
      Serial.println(volume.fatType(), DEC);
      Serial.println();
      
      volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
      volumesize *= volume.clusterCount();       // we'll have a lot of clusters
      if (volumesize < 8388608ul) {
        Serial.print("Volume size (bytes): ");
        Serial.println(volumesize * 512);        // SD card blocks are always 512 bytes
      }
      Serial.print("Volume size (Kbytes): ");
      volumesize /= 2;
      Serial.println(volumesize);
      Serial.print("Volume size (Mbytes): ");
      volumesize /= 1024;
      Serial.println(volumesize);
    
      
      Serial.println("\nFiles found on the card (name, date and size in bytes): ");
      root.openRoot(volume);
      
      // list all files in the card with date and size
      root.ls(LS_R | LS_DATE | LS_SIZE);
    }
    
    
    void loop(void) {
      
    }
    Firstly, I decided to use the basic version, without any changes in pinout of SPI. As a result in the Serial I got this:

    Code:
    Initializing SD card...Wiring is correct and a card is present.
    
    
    Card type: SDHC
    
    Could not find FAT16/FAT32 partition.
    Make sure you've formatted the card
    It made me think, that I got a problem with my card, I should format it properly, so I made it with this formatter (https://www.sdcard.org/downloads/formatter/), it changed nothing.


    But then the courier came, I got a package with Teensy 4.0, so I instantly soldered pins to it and connected it to the whole circuit - bingo!, the basic SPI (using CS - 10, MOSI - 11, MISO - 12, SCK - 13) worked well! Notice, that I didn't change the circuit, didn't format SD card, change the code, etc. I got this message in serial:

    Code:
    Initializing SD card...Wiring is correct and a card is present.
    
    
    Card type: SDHC
    
    
    Volume type is FAT32
    
    
    
    Volume size (bytes): 3952607232
    
    Volume size (Kbytes): 3859968
    
    Volume size (Mbytes): 3769
    
    
    Files found on the card (name, date and size in bytes): 
    
    SYSTEM~1/     2021-06-24 11:39:14
    
      WPSETT~1.DAT  2021-06-24 11:39:14 12
    
      INDEXE~1      2021-06-24 11:39:14 76
    
    TEST.TXT      2000-01-01 01:00:00 448
    
    DROPBO~1.DEV  2021-06-24 11:40:16 56
    
    1504TO~1.TXT  2020-08-06 15:27:30 213
    I decided to go level up - I soldered SCK to the pin 27 (SCK1) - to avoid the collision with FreqCount library - first fail - It didn't work. I thought, maybe I cannot mix SCK1 pins with SCK - soldered also pin 26 as MOSI, and connected CS as pin 0, and MISO as 1 - still, in the serial message about wrong connection. Then I found out interesting thing - I can declare anything in a line SPI.setSCK(x) - if I put 50 or 35 as 'x' Teensy ignore it, it think, that SCK is still declared as 13. Here is a screenshot:

    Click image for larger version. 

Name:	error.jpg 
Views:	9 
Size:	105.8 KB 
ID:	25119

  19. #19
    Junior Member
    Join Date
    May 2020
    Location
    Poland
    Posts
    11
    Ok, I fixed this error on teensy 3.2, but I don't know why it worked. I changed the speed of the CPU from 72 MHz (error about wrong formatted SD card) to 24 MHz (no error). Then I changed the SCK to pin 14 - it worked also. How? Why?

    The other question is? Should I change the speed of the whole CPU (I use also FreqCount library so it isn't a good thing to slow down the whole Teensy) or can I change only the speed of saving to SD?

  20. #20
    Senior Member
    Join Date
    Nov 2015
    Location
    Cold hollow VT
    Posts
    201
    It appears that by changing the CPU speed from 72MHz to 24MHz also has the effect of slowing down the SDcard clock speed. I don't see in your original code anything to slow down the SDcard speed such as >>> (!SD.begin(sdCs), SPI_HALF_SPEED); <<< which will change the SDcard clock speed to a slower one. There may be other 'code words' to set other clock speeds but I found this worked for me and have not bothered to explore them.

    You are correct that you can't inter-mix up clocks from different SPI busses.

    By changing the CPU clock speed you are changing the rate at which the CPU (and some peripherals) operates which is different (not related) than the speed of the logic circuitry (transistors) on the chip. I have not used the FreqCount library so I don't know what factor it relies on, as there are several methods to determine frequency and delay periods. Changing clock rate may affect the resolution of the measurement depending on the method used.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •