Pulses counting in intervals with teensy 3.2

Status
Not open for further replies.

brogue

Member
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):

example.png

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?
 
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.
 
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:
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?

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.

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.
 
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.

IMG_1402.jpg

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?

1.JPG
(https://www.analog.com/en/analog-di...g-comparator-instability-with-hysteresis.html)
 
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.
 
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?
 
Is it possible to connect FreqCount library and SD library in one program?"
yes.
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.
brogue said:
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?
 
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.
 

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.

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.

Where is the sourcecode?
The sourcecode doesn't exist. Firstly, I have to manage with the hardware problems.
 
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.
 
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...
 
@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.)
 
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-Teensy-4-1-Connecting-multiple-SPI-devices it should be okay.

@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.
 
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.
 
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/teensy-tutorial-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:

error.jpg
 
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?
 
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.
 
Status
Not open for further replies.
Back
Top