Ultrasonic Flow Meter with TDC-GP22 using Arduino UNO

Hello all,

I'm trying to do the project of an Ultrasonic Flow Meter with TDC-GP22 using Arduino UNO. I used the library of leokoppel with a simple code to do the test:

#include "GP22.h"
#include <SPI.h>
#include <avr/io.h>


/*
 *
 * Test setup (Arduino Uno, through 5->3.3V level shift)
 *     10 -> SS
 *     11 -> MOSI
 *     12 -> MISO
 *     13 -> SCK
 *     2  -> INT
 *     5V -> VCC
 *     GND -> GND
 *     4 -> DS18B20 temperature sensor (optional)
 */


const bool DEBUG = 1;
const int FAST_MODE = 1;
const int PIN_INT = 2;


GP22 tdc(PIN_INT, DEBUG);

float cycleFactor_ns = 0;


void setup() {
  
  Serial.begin(115200);
  Serial.println("Go !");
  
  tdc.init();

  tdc.writeRegister(0, CFG_KEEP_DEFAULT_BITMASKS[0]
                      
                      | CFG0_ANZ_FIRE_START_2*1        // Fire 20  (4)+16
                      | CFG0_DIV_FIRE_1*1
                      | CFG0_DIV_FIRE_0*1             // Fire divided by 4
                      | CFG0_DIV_CLKHS_0*0             // Clock divided by 1
                      | CFG0_START_CLKHS_START_1 * 1    // Setting time 480µs
                      | CFG0_CALIBRATE * 1              // Calibration on 
                      | CFG0_MESSB2 * 1             // Measurement mode 2
                      
                      | CFG0_ANZ_PORT               //Modification with temperature(not used yet)
                      | CFG0_TCYCLE
                      | CFG0_ANZ_FAKE 
                      | CFG0_SEL_ECLK_TMP
                      
                      | 0x00
                     );
                     
  tdc.writeRegister(1, CFG_KEEP_DEFAULT_BITMASKS[1]
                      | CFG1_HIT1_0 * 1     // Calculate 1st Stop Ch1 - Start
                      | CFG1_HIT2_1 * 1
                      | CFG1_HITIN1_2 * 1   // Wait for 4 hit on channel 1
                      | CFG1_HITIN2_1 * 0   // Wait for 0 hits on channel 2
                      | CFG1_SEL_START_FIRE * 1
                      | CFG1_EN_FAST_INIT * 0
                      | 0x00
                     );

  tdc.writeRegister(2, CFG_KEEP_DEFAULT_BITMASKS[2]
                      | CFG2_RFEDGE1 * 0           // Ch 1 sensitive to one edge
                      | CFG2_EN_INT_ALU            // Enable interrupt on ALU ready
                      | CFG2_EN_INT_TDC_TIMEOUT    // Enable interrupt on TDC timeout
                      | CFG2_DELVAL1_12            // DELVAL1= 5000
                      | CFG2_DELVAL1_9
                      | CFG2_DELVAL1_8
                      | CFG2_DELVAL1_7
                      | CFG2_DELVAL1_3
                      | 0x00
                     );
                     
  tdc.writeRegister(3, CFG_KEEP_DEFAULT_BITMASKS[3]
                      | CFG3_EN_AUTOCALC_MB2     // Automatic calculation of all enabled hits(mode 2 only)
                      | CFG3_EN_FIRST_WAVE       // Automatic first hit detection
                      | CFG3_SEL_TIMO_MB2_1      // Predivider for timeout = 1024µs 
                      | CFG3_DELVAL2_15          // 10 periods after first hit for 3rd stop
                      | CFG3_DELVAL2_13
                      | CFG3_DELVAL2_9           // 9 periods for 2nd stop
                      | CFG3_DELVAL2_6
                      | CFG3_DELVAL2_3           // 8 periods for 1st stop
                      | 0x00
                     );

  tdc.writeRegister(4, CFG_KEEP_DEFAULT_BITMASKS[4]
                      | CFG4_KEEP_DEFAULT_2 * 0
                      | CFG4_KEEP_DEFAULT_1 * 1 
                      | CFG4_DELVAL3_8 * 0       // Enable pulse width measurement
                      | CFG4_DELVAL3_7 * 0       // Rising edge
                      | CFG4_DELVAL3_6           // Additional offset shift by +20mv
                      | CFG4_DELVAL3_5 * 0       // No offset -20mv
                      | 0x00
                     );
                     
  tdc.writeRegister(5, CFG_KEEP_DEFAULT_BITMASKS[5]
                      | CFG5_CON_FIRE_1          // Enable output fire up  
                     );
                     
  tdc.writeRegister(6, CFG_KEEP_DEFAULT_BITMASKS[6]
                      | CFG6_EN_ANALOG           // Enable Analog section
                      | CFG6_NEG_STOP_TEMP       // Use internal Schmitt trigger 
                      | CFG6_TW2_1               // 300µs to charge up the capacitor
                      | CFG6_TW2_0                
                      | CFG6_FIREO_DEF           // Low level by default of the inactive fire buffer
                      | CFG6_QUAD_RES            // Enable quad resolution
                      | CFG6_ANZ_FIRE_END_0*1      // Fire 20    4+(16)   
                                    
                     );



  tdc.printConfigRegisters();

  byte a = tdc.readRegister(READ_REG_1);             
  Serial.println(a,HEX);
  Serial.println("Test communication: ");
  Serial.print(tdc.testCommunication());
 } 



void loop() {

  tdc.sendOpcode(OPCODE_INIT);
  tdc.sendOpcode(OPCODE_START_TOF_RESTART);


  tdc.waitForInterrupt(10000000);
  delay(20);
  Serial.println(tdc.readRegister(READ_RES_3),HEX);

}

The configurations of the registers are copied from the Application Note, from page 22 to page 25. I didn't use the temperature sensor so I jumped those steps related to that. No calibration neither. I just want to get some results of time of flight to be able to calculate the distance between two sensors for now. But the interrupt doesn't seem to work. What I got:

Go !
attached pinChangeISR_debug

Register 0: 0x430be800
Register 1: 0x21444000
Register 2: 0xa0138800
Register 3: 0xd0a24800
Register 4: 0x10004000
Register 5: 0x40000000
Register 6: 0xc0c06100

21
Test communication: 
\/Test took 180 us
1
69978000
69978000
69978000
69978000
69978000
69978000
69978000
...

21 is the first byte of register 1, and 1 is the result of testcommunication(). These two means the test of communication is successful. But the results of reading RES_3 are always the same, and the waitForInterrupt() doesn't work(maybe the code shouldn't be written like this) -- Timeout all the time.

The two 1MHz ultrasonic sensors are put on the two sides of an iron panel (thickness 2.2mm), and I managed to get the signal with the help of oscilloscope (please see the attachments, the blue one is the signal of transmitter before amplification, green one is after amplification, yellow one is the signal of receiver), which seems to be correct. So I wonder how to read the measurement results correctly.

Here is the datasheet of TDC-GP22
This is my Ultrasonic Sensor
And my device of GP22 is the CJMCU-22

Any help appreciated,
Yinan

Or maybe this one looks better, with the rose one stands for the interrupt, which never goes to 0.

1 Like

Hello Yinan,

how did you wire everything up ? A picture/schematic would be helpfull.

Hello,

I attach it below.

For the pin SSN,SCK, (MO)SI, they are uni-directional so we can simply use a voltage divider. The (MI)SO pin's direction is opposite to the others so I had to use a bi-directional channel(TX) of the logic level converter. The direction of INT is unknown, to make sure it works, I used also a bi-directional channel. And I set the RTN pin to 1.

The right part of the picture is an amplifier, you may temporarily ignore it as it should work even without amplification.

Hi
i am working on a similar project and I am not finished, but here is what stuck out to me. You use mesurementmode2 and the datasheet states on P56 that calibration is needed for this mode. You specifically say that you do not calibrate your system so the result you get maybe default value of register 3. Also with speed of sound in Iron 5120 m/s and thickness 0,0022m you get a ToF of about 430 ns with your iron plate. The problem is, the measurement mode 2 only supports TOF from 500ns to 4ms (P 53). The wired thing is, that your signal shows a TOF of at least 2 us so that does not really make sense either.

I hope this helps after such a long time.
zadu

I also use for my hobby project the so called cjmcu board.
Apart from the obvious Vcc/GND and SPI pins I am struggling to find the corresponding pins to GP22 datasheet!
INT should be Interrupt pin but what about the DIS/FIN/SP1/SP2/PT1/PT2/THT/TCD pins shown in the image below?
Any help is welcomed.

1 Like