Stumped reading message twice

Trying to figure out how to make this message be read twice before turning on relay.

Message is coming from a Keyless Entry Module and a Class 2 Data transciever.

So basically you have to hit the button on the remote twice to activate relay.

This works as is, just wont to have to push button twice.


#include "J1850VPWCore.h"

#define J1850VPW_RX 2 // INT0 on Uno, INT4 on Mega
#define J1850VPW_TX 9
#define SLEEP 5
#define _4XLOOP 7

uint8_t RKE = (0xA8, 0xC7, 0xB0, 0xA0, 0x13);

void setup()
{
  Serial.begin(115200);
  pinMode(12, OUTPUT);

  // MC33390 settings.
  pinMode(SLEEP, OUTPUT);
  digitalWrite(SLEEP, HIGH); // enable PCI-bus transmitter (receiver is always enabled), HIGH: enable, LOW: disable
  // pinMode(_4XLOOP, INPUT); // PCI-bus loopback mode: transmitted message is immediately received (for testing only)
  pinMode(_4XLOOP, OUTPUT);
  digitalWrite(_4XLOOP, LOW);                // PCI-bus waveshaping - LOW: enabled, HIGH: disabled
  VPW.onMessageReceived(VPWMessageReceived); // subscribe to the message received event and call this function when a PCI-bus message is received
  VPW.begin(J1850VPW_RX, J1850VPW_TX, ACTIVE_HIGH);
}

void VPWMessageReceived(uint8_t *RKEmessage, uint8_t messageLength)
{
  for (uint8_t i = 0; i < 5; i++)
  {
    if ((RKEmessage[0] == 0xA8) && (RKEmessage[1] == 0xC7) && (RKEmessage[2] == 0xB0) && (RKEmessage[3] == 0xA0) && (RKEmessage[4] == 0x13))
    {
      if (RKEmessage[i] = RKE)
        digitalWrite(12, HIGH); // turn relay on
      Serial.print("ON");       // testing
      delay(1000);  //long delay for testing
      digitalWrite(12, LOW); // turn relay off
      Serial.print("OFF");   // testing
    }
  }
}

void loop()
{
}

Please follow the forum rules and post code that will compile and demonstrate the problem.

The snippet doesn't make much sense to me, and there appears to be nothing in the snippet that reads a message. Or a button.

I see you updated your original post, which makes the thread hard to follow.

What is the following line suppose to do? The compiler probably emits some warnings, if not fatal errors.

      if (RKEmessage[i] = RKE)

"=" is the assignment operator. If you meant to do a comparison, use "==". However, RKE is a pointer to a C-string (a zero terminated character array), and cannot be compared to a byte value.

Please take a few moments to describe what this code should do, and perhaps you will get useful help.

I got this to work. Now to figure out how to make it timeout if second message isnt sent

void VPWMessageReceived(uint8_t *RKEmessage, uint8_t messageLength)
{
  uint8_t RKE = 0xA8C7B0A013;
  for (uint8_t i = 0; i < 5; i++)
  {
    if (RKEmessage[i] == RKE)
    {
      buttonPress++;
    }
    if (RKEmessage[i] == RKE && buttonPress == 2)
    {
      digitalWrite(12, HIGH);
      Serial.println("ON");
      delay(100000);
      digitalWrite(12, LOW);
      Serial.println("OFF");
      buttonPress = 0;
    }
  }
}

Use a variable and remember the first time that a correct message was received. Wait for the second message; while waiting, check remembered time and if it's longer than the timeout time, start from the beginning. Use a millis() based approach.

I was trying the millis() approach, but not sure where to start. I just keep copying and pasting until something works.

This does not work.


#include "J1850VPWCore.h"

#define J1850VPW_RX 2 // INT0 on Uno, INT4 on Mega
#define J1850VPW_TX 9
#define SLEEP 5
#define _4XLOOP 7

int buttonPress = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
const unsigned long timeout = 5000;

void setup()
{
  Serial.begin(115200);
  pinMode(12, OUTPUT);

  // MC33390 settings.
  pinMode(SLEEP, OUTPUT);
  digitalWrite(SLEEP, HIGH); // enable PCI-bus transmitter (receiver is always enabled), HIGH: enable, LOW: disable
  // pinMode(_4XLOOP, INPUT); // PCI-bus loopback mode: transmitted message is immediately received (for testing only)
  pinMode(_4XLOOP, OUTPUT);
  digitalWrite(_4XLOOP, LOW);                // PCI-bus waveshaping - LOW: enabled, HIGH: disabled
  VPW.onMessageReceived(VPWMessageReceived); // subscribe to the message received event and call this function when a PCI-bus message is received
  VPW.begin(J1850VPW_RX, J1850VPW_TX, ACTIVE_HIGH);
}

void VPWMessageReceived(uint8_t *RKEmessage, uint8_t messageLength)
{
  currentMillis = millis();
  uint8_t RKE = 0xA8C7B0A013;

  for (uint8_t i = 0; i < 5; i++)
  {
    if (RKEmessage[i] == RKE)
    {
      buttonPress++;
    }

    if (currentMillis - previousMillis <= timeout)
    {
      previousMillis = currentMillis;

      if (RKEmessage[i] == RKE && buttonPress == 2)
      {
        digitalWrite(12, HIGH);
        Serial.println("ON");
        delay(100000);
        digitalWrite(12, LOW);
        Serial.println("OFF");
        buttonPress = 0;
      }
    }
  }
}

void loop()
{
  
}

You will first have to fix that. An uint8_t can not hold a 5 byte integer. I suggest that you go back to the approach used in your opening post.

I see that you have a similar problem in the code in your opening post. The below code demonstrates that you do not get what your expect

uint8_t RKE = (0xA8, 0xC7, 0xB0, 0xA0, 0x13);

void setup()
{
  Serial.begin(115200);
  Serial.println(RKE);
}

void loop()
{
}

This print '19' which is the last byte of your RKE variable.

Please try to explain what the intention of below is

    if ((RKEmessage[0] == 0xA8) && (RKEmessage[1] == 0xC7) && (RKEmessage[2] == 0xB0) && (RKEmessage[3] == 0xA0) && (RKEmessage[4] == 0x13))
    {
      if (RKEmessage[i] = RKE)

Once the first if condition is true the second one will also be true (if i == 4).

Not tested but compiles; comments should explain the code, else ask.

#include "J1850VPWCore.h"

#define J1850VPW_RX 2 // INT0 on Uno, INT4 on Mega
#define J1850VPW_TX 9
#define SLEEP 5
#define _4XLOOP 7

// not used; demonstrate correct initialisation of RKE
//const uint8_t RKE[] = {0xA8, 0xC7, 0xB0, 0xA0, 0x13};

// relay pin
const uint8_t pinRelay = 12;
// timeout between button presses
const uint32_t btnTimeout = 1000;

void setup()
{
  Serial.begin(115200);
  pinMode(pinRelay, OUTPUT);

  // MC33390 settings.
  pinMode(SLEEP, OUTPUT);
  digitalWrite(SLEEP, HIGH); // enable PCI-bus transmitter (receiver is always enabled), HIGH: enable, LOW: disable
  // pinMode(_4XLOOP, INPUT); // PCI-bus loopback mode: transmitted message is immediately received (for testing only)
  pinMode(_4XLOOP, OUTPUT);
  digitalWrite(_4XLOOP, LOW);                // PCI-bus waveshaping - LOW: enabled, HIGH: disabled
  VPW.onMessageReceived(VPWMessageReceived); // subscribe to the message received event and call this function when a PCI-bus message is received
  VPW.begin(J1850VPW_RX, J1850VPW_TX, ACTIVE_HIGH);
}

void VPWMessageReceived(uint8_t *RKEmessage, uint8_t messageLength)
{
  // if a message is a match
  bool isMatch = false;

  // remember button count
  static uint8_t buttonCount;
  // remember time of first button
  static uint32_t firstBtnTime;

  // check for match
  if ((RKEmessage[0] == 0xA8) && (RKEmessage[1] == 0xC7) && (RKEmessage[2] == 0xB0) && (RKEmessage[3] == 0xA0) && (RKEmessage[4] == 0x13))
  {
    isMatch = true;
    // if it's first button press
    if (buttonCount == 0)
    {
      // remember the time
      firstBtnTime = millis();
    }
    // increment button counter
    buttonCount++;
  }

  // no match
  if (isMatch == false)
  {
    // nothing to do
    return;
  }

  // check for timeout between first and second button press
  if (buttonCount == 1 && millis() - firstBtnTime >= btnTimeout)
  {
    // reset button counter
    buttonCount = 0;
    Serial.println(F("Timeout"));
    // nothing else to do
    return;
  }

  // got two button presses
  if (buttonCount == 2)
  {
    // reset button counter
    buttonCount = 0;

    // turn relay on
    digitalWrite(pinRelay, HIGH);
    Serial.print("ON");     // testing
    //long delay for testing
    delay(1000);
    // turn relay off
    digitalWrite(pinRelay, LOW);
    Serial.print("OFF");    // testing
  }
}

void loop()
{
}

This code works the way I want. I have to push the button twice. Only problem is, it need to detect the second button push within say 5 seconds. If not it needs to start over.


#include "J1850VPWCore.h"

#define J1850VPW_RX 2 // INT0 on Uno, INT4 on Mega
#define J1850VPW_TX 9
#define SLEEP 5
#define _4XLOOP 7

int buttonPress = 0;

void setup()
{
  Serial.begin(115200);
  pinMode(12, OUTPUT);

  // MC33390 settings.
  pinMode(SLEEP, OUTPUT);
  digitalWrite(SLEEP, HIGH); // enable PCI-bus transmitter (receiver is always enabled), HIGH: enable, LOW: disable
  // pinMode(_4XLOOP, INPUT); // PCI-bus loopback mode: transmitted message is immediately received (for testing only)
  pinMode(_4XLOOP, OUTPUT);
  digitalWrite(_4XLOOP, LOW);                // PCI-bus waveshaping - LOW: enabled, HIGH: disabled
  VPW.onMessageReceived(VPWMessageReceived); // subscribe to the message received event and call this function when a PCI-bus message is received
  VPW.begin(J1850VPW_RX, J1850VPW_TX, ACTIVE_HIGH);
}

void VPWMessageReceived(uint8_t *RKEmessage, uint8_t messageLength)
{
  uint8_t RKE = 0xA8C7B0A013;  //message to look for

  for (uint8_t i = 0; i < 5; i++)
  {
    if (RKEmessage[i] == RKE)
    {
      buttonPress++;
    }
      if (RKEmessage[i] == RKE && buttonPress == 2)
      {
        digitalWrite(12, HIGH);
        Serial.println("ON");
        delay(100000);   //long delay for testing
        digitalWrite(12, LOW);
        Serial.println("OFF");
        buttonPress = 0;
      }
    }
  }


void loop()
{
}

I got this to work like I want. Prob not the best way.


#include "J1850VPWCore.h"

#define J1850VPW_RX 2 // INT0 on Uno, INT4 on Mega
#define J1850VPW_TX 9
#define SLEEP 5
#define _4XLOOP 7

const uint32_t btnTimeout = 2000;
static uint8_t buttonCount;
static uint32_t firstBtnTime;

void setup()
{
  Serial.begin(115200);
  pinMode(12, OUTPUT); // relay pin

  // MC33390 settings.
  pinMode(SLEEP, OUTPUT);
  digitalWrite(SLEEP, HIGH); // enable PCI-bus transmitter (receiver is always enabled), HIGH: enable, LOW: disable
  // pinMode(_4XLOOP, INPUT); // PCI-bus loopback mode: transmitted message is immediately received (for testing only)
  pinMode(_4XLOOP, OUTPUT);
  digitalWrite(_4XLOOP, LOW);                // PCI-bus waveshaping - LOW: enabled, HIGH: disabled
  VPW.onMessageReceived(VPWMessageReceived); // subscribe to the message received event and call this function when a PCI-bus message is received
  VPW.begin(J1850VPW_RX, J1850VPW_TX, ACTIVE_HIGH);
}

void VPWMessageReceived(uint8_t *RKEmessage, uint8_t messageLength)
{

  uint8_t RKE = 0xA8C7B0A013; // message to look for

  for (uint8_t i = 0; i < 5; i++)
  {
    if (RKEmessage[i] == RKE)
    {
      firstBtnTime = millis();
      buttonCount++; // increment button counter
      Serial.println(buttonCount);
    }

    if (RKEmessage[i] == RKE && buttonCount == 2)
    {
      digitalWrite(12, HIGH);
      Serial.println("ON");
      delay(100000); // long delay for testing
      digitalWrite(12, LOW);
      Serial.println("OFF");
      buttonCount = 0; // reset button counter
      Serial.println(buttonCount);
    }
  }
}

void loop()
{
  if (buttonCount == 1 && millis() - firstBtnTime >= btnTimeout)
  {
    buttonCount = 0;
    Serial.println(millis());
    Serial.println(firstBtnTime);

    Serial.println(buttonCount);
  }
}