I'm working with an RSSV013010W0101-U1930 proximity sensor and an Arduino Nano, and I've run into a recurring error that I have a few hunches on, but can't quite figure out.
The device is meant to count the number of times something enters then leaves its field of view, and display that information on a standard hd44780 16x2 LCD display.
Whenever an object enters the device's field of view, the proximity sensor asserts a logic low to the Arduino Nano's D2 pin and returns to logic high when its field of view is clear. Additionally, the device can also be configured via UART communication, which is where I discovered the problem.
Aside from power and ground connections, the proximity sensor is connected to the Nano in two places TX/OUT to D2, and RX/IN to D7. This is so that the device can be configured or have its current configuration confirmed via UART communication, which in this case is done with Arduino's SoftwareSerial library.
First off, the device was working perfectly for multiple days, using the code below:
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <SoftwareSerial.h>
//#define DEBUG
#define PROX_INIT_ADDR 1
#define BATTERY_MONITOR A0
LiquidCrystal lcd(9, 8, 13, 12, 11, 10); //rs, enable, d4, d5, d6, d7)
byte Battery[] = {
B01110,
B10001,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111
};
byte Clock[] = {
B01110,
B10101,
B10101,
B10101,
B10011,
B10011,
B10001,
B01110
};
byte Pace[] = {
B00000,
B00100,
B01010,
B10001,
B00100,
B01010,
B10001,
B00000
};
int movementTimeStart = 0;
int movementTimeEnd = 0;
int movementTimeCheck = 0;
int totalExerciseTime = 0;
bool movementFlag = false;
unsigned int Seconds = 0;
unsigned int Minutes = 0;
int mouseWheelCounter ;
int previousCount;
void setup() {
Serial.begin(115200);
lcd.begin(16,2);
lcd.createChar(1, Battery);
lcd.createChar(2, Clock);
lcd.createChar(3, Pace);
lcd.setCursor(0,0);
lcd.print("WELCOME TO");
lcd.setCursor(0,1);
lcd.print("CV COUNTER");
delay(3000);
lcd.clear();
setupProximitySensor();
bool distanceCalibrationCheck = EEPROM.read(PROX_INIT_ADDR);
if(distanceCalibrationCheck != true)
{
//runDistanceLearning();
//EEPROM.write(true, PROX_INIT_ADDR);
}
pinMode(2, INPUT);
delay(30);
//attachInterrupt(digitalPinToInterrupt(2), CrystalDisplay, FALLING);
Serial.println("SETUP COMPLETE");
}
void loop() {
#ifdef DEBUG
//Serial.println("looping");
#endif
lcdPrintBattery();
if(digitalRead(2) == LOW)
{
while(digitalRead(2) == LOW)
{
delay(1);
}
CrystalDisplay();
}
if(mouseWheelCounter != previousCount)
{
Serial.println(mouseWheelCounter);
lcdPrintWheelCount();
}
if (movementFlag == true)
{
lcdPrintTime();
movementTimeCheck = millis();
if((movementTimeCheck - movementTimeEnd) > 3000)
{
movementFlag = false;
#ifdef DEBUG
Serial.println("Movement ended");
#endif
}
}
previousCount = mouseWheelCounter;
}
void lcdPrintWheelCount()
{
char wheel_buf[] = "";
sprintf(wheel_buf, "\3: %d", mouseWheelCounter);
lcd.setCursor(8, 1);
//lcd.rightToLeft();
lcd.print(wheel_buf);
#ifdef DEBUG
Serial.println(wheel_buf);
#endif
}
void lcdPrintTime()
{
char time_buf[] = "";
sprintf(time_buf, "\2 %d:%d", Minutes, Seconds);
lcd.leftToRight();
lcd.setCursor(0,1);
lcd.print(time_buf);
#ifdef DEBUG
Serial.println("Next movement detected!");
#endif
}
void CrystalDisplay()
{
Serial.println("Interrupt Detected");
mouseWheelCounter++;
if (mouseWheelCounter == 10000)
{
mouseWheelCounter=0;
}
if(movementFlag == false)
{
movementTimeStart = millis();
movementFlag = true;
#ifdef DEBUG
Serial.println("First movement detected!");
#endif
}
else
{
movementTimeEnd = millis();
int exerciseTime = ((movementTimeEnd - movementTimeStart)/1000);
totalExerciseTime += exerciseTime;
Seconds = totalExerciseTime % 60;
Minutes = totalExerciseTime / 60;
}
}
void setupProximitySensor()
{
uint8_t tx_buf[6];
tx_buf[0] = 0x55;
tx_buf[1] = 0xC0;
tx_buf[2] = 0x0A;
tx_buf[3] = 0x01;
tx_buf[4] = 0x08;
tx_buf[5] = 0x28;
uint8_t special_buf[3];
special_buf[0] = 0x55;
special_buf[1] = 0x19;
special_buf[2] = 0x6E;
SoftwareSerial tempSerial(2, 7);
tempSerial.begin(9600);
tempSerial.write(tx_buf, 6);
//delay(750);
//tempSerial.write(special_buf, 3);
tempSerial.end();
delay(3000);
}
void lcdPrintBattery()
{
char bat_buf[] = "";
unsigned int batteryValue = analogRead(BATTERY_MONITOR);
unsigned int batteryPercent = ((batteryValue * 100)/1023);
sprintf(bat_buf, "\1%d%%",batteryPercent);
lcd.setCursor(10, 0);
lcd.print(bat_buf);
}
void runDistanceLearning()
{
pinMode(2, INPUT);
pinMode(7, OUTPUT);
digitalWrite(7, LOW);
delay(500);
digitalWrite(7, HIGH);
bool readVal = digitalRead(2);
bool flipVal = !readVal;
while(readVal != flipVal)
{
readVal = digitalRead(2);
}
Serial.println("DISTANCE LEARNING COMPLETED");
return;
}
I've been testing a PCB for the device, and only now have problems arisen on both the breadboard design and the PCB, those problems being that when I check the voltage on the UART buses, the logic HIGH now reads as 1.2V, rather than 5V.
One of the proximity sensors I tested was actually becoming quite hot, though I haven't felt a notable temperature rise in the other sensors I tried. I've also checked, checked and checked again all the connections and I'm not finding any short or open circuits. What's more, when I remove the proximity sensor, the Arduino's logic levels return to 5V.
This suggests to me that something is damaging the proximity sensors, at least on the PCB, but I can't figure out what, since I cannot find any shorts or opens.
edit: I can confirm now that whatever is going wrong is specifically happening on the PCB setup, though I'm not sure what. The only real difference I've found in terms of continuity is that I'm using a potentiometer on the breadboard to set the contrast of the LCD, while I'm just tying it straight to ground on the PCB (technically there's a voltage divider, but the setup is currently only using a 0 ohm for R1, while R2 is unpopulated)
Oh, and one more thing; I tried running the proximity sensor when not attached to the arduino in any way, and I got this in response:
Normally the device only asserts a logic low when something has entered its field of view, but no matter what I do, it's constantly low; jostling it in the breadboard, moving it to new locations, waving my hand over it to see if this one was configured to provide a logic HIGH when something enters its field of view, nothing.