Hello Hackers! Today we have a really interesting topic.
Searching the internet, I didn't find any simple solution on "How to read data from car parking sensors," so I decided to write a short and easy-to-understand article to help robotics engineers reverse engineer the cheapest waterproof ultrasonic sensors on the market.
Cheapest Chinese sensors that you can find on the market (Alibaba, Aliexpress, Taobao, Amazon, etc.)
12-volt power supply (Picture 2);
Arduino board with 5-volt logic (skip ARM versions with 3.3 volts);
Any oscilloscope or logic analyzer;
Computer with Arduino IDE.
First, we need to disassemble the sensor case (Picture 5).
We need to connect the black wire (pink dot) to “-” and the red wire (blue dot) to “+” of our 12-volt power supply. The green dot (GND) is connected to the GND of the Arduino board, and the red dot (DA) to any PWM-supported PIN of the Arduino board—PIN 3 in my case. As you can see, we have 4 connectors to our sensors. We will not connect them because we need to find each sensor's address; it will be easy to detect them in that case (Picture 6).
Before we download the Arduino sketch, we need to gather some information about the PWM signal used to send data to the parking display:
To get all this necessary information, we will use an oscilloscope. Connect it to the "GND" (green dot) and "DA" (red dot) pins, and don't forget to power on the sensor's board and Arduino.
Finally, we received 4 different packets. Don't panic if you don't understand, I will describe the first packet in detail with an explanation.
From this picture, we see that this is a HIGH logic PWM signal because the default value is 0 volts in our pin, and then it rises to 5 volts (Pink arrow).
Next, we see the start bit - marked as green ST (the longest signal).
We also see the body of the packet. I have marked only the high length of each signal with red and blue colors. Red represents a long signal (logic 1), while blue represents a short signal (logic 0).
The duration of the long, short, and start signals we will measure later. From this screen, we only need to extract the real binary data from each packet and write it down.
We got this data:
packet 1. 1000 1010 1111 1111 0
packet 2. 1000 1001 1111 1111 0
packet 3. 1000 1000 1111 1111 0
packet 4. 1000 1011 1111 1111 0
Next, we need to measure the duration of short, long, start bit, and time duration between the packets.
As you can see from the picture, we see green lines, that measure the duration. In our case T = 220uS. It is the duration of the long bit.
Finally, we got interesting data:
The type of PWM signal is HIGH;
The packet length is 2 bytes or 16 bits;
The number of packets that sends is 4;
The time between packets is 40mS;
The duration of the start bit is 1.02mS;
The duration of LOW is 80nS and the HIGH bit is 220nS;
Now we are ready to code a sketch.
// our pin that supports PWM
int inputPin = 3;
// our packet, where we will store our 16bits information about sensor.
unsigned int packet = 0;
// our bit duration, for short = 80nS, long = 220nS and start bit = 1.02mS
unsigned long pulseDuration = 0;
void setup() {
pinMode(inputPin, INPUT);
Serial.begin(2000000);
}
void loop() {
// pulseIn is a build-in function, that waits for HIGH signal.
// We have defined that our logic is PWM-HIGH, that's why we are using HIGH.
// 20.000 is a timeout of waiting for signal.
pulseDuration = pulseIn(inputPin, HIGH, 20000);
// We detect the start packet pulse. In our case the start bit is 1.02mS,
// so it is between these values:
if (pulseDuration > 900 && pulseDuration < 1040) {
// We have successfully detected start bit, now we need to read the body of the packet.
packet = 0;
// Only read 16 bits of data.
for (int i = 15; i >= 0; i--) {
// Read packet (only HIGH bits, zeros are ignored, because we already have it)
pulseDuration = pulseIn(inputPin, HIGH, 3000);
// we detect only LONG bits with 220nS duration (logical 1);
if (pulseDuration > 210 && pulseDuration < 250) {
bitSet(packet, i);
}
}
// Print the packet;
Serial.println(packet, BIN);
}
}
We got this output from Arduino IDE. Now, we can compare it with our investigated values from our oscilloscope:
1000101111111111
1000100111111111
1000101011111111
1000100011111111
Great! We have verified that the code is working fine and we got the same values from the oscilloscope.
Our packet is divided into 2 parts. First 8 bits is the address of the sensor. The last 8 bits is the measured distance.
10001000 11111111
10001001 11111111
10001010 11111111
10001000 11111111
As we remember, we didn’t connect the sensors to board, that’s why we are receiving “11111111”.
We can change a code and split the address and values using this logic:
// We delete last 8 bits of our packet to get the address value;
byte sensorAddressCheck = (byte)(packet >> 8);
// Using logical operation AND we remove first 8 bits;
byte sensorValueCheck = (byte)(packet & B11111111);
Now we have this code:
int inputPin = 3;
unsigned int packet = 0;
byte sensorValue = 0;
byte sensorAddress = 0;
unsigned long pulseDuration = 0;
void setup() {
pinMode(inputPin, INPUT);
Serial.begin(2000000);
}
void loop() {
pulseDuration = pulseIn(inputPin, HIGH, 20000);
if (pulseDuration > 900 && pulseDuration < 1040) {
sensorAddress = 0;
sensorValue = 0;
packet = 0;
for (int i = 15; i >= 0; i--) {
pulseDuration = pulseIn(inputPin, HIGH, 3000);
if (pulseDuration > 210 && pulseDuration < 250) {
bitSet(packet, i);
}
}
byte sensorAddressCheck = (byte)(packet >> 8);
byte sensorValueCheck = (byte)(packet & B11111111);
Serial.print("Sensor addr: ");
Serial.print(sensorAddressCheck, BIN);
Serial.print(" value: ");
Serial.println(sensorValueCheck);
}
}
Arduino output:
Sensor addr: 10001011 value: 255
Sensor addr: 10000001 value: 80
Sensor addr: 10000010 value: 82
Sensor addr: 10001000 value: 255
Congrats! You have successfully reversed the PWM signal and I hope that it will help you in your robotics beginnings! If you want to know the distance in centimeters, additional work should be done. The general process is simple: You can put the roulette on the floor and take a box.
A little creative work and you will get a correlation table between 0-255 values from the sensor with your roulette. Thanks for your time!
PS. This work is part of a big project (Picture 7). If you want to learn more, subscribe to my channel! Thanks!