Canbus PWM control for 1 output

Want to see if anyone can help me out with an issue I'm having in a sketch that I'm working on. The nano is sending canbus messages to and from a computer software program that I want to keep that control in place. However, I'm trying to set it where if Digital 5 is set to high over canbus, that it turns this 1 input on as PWM based on the pot connected to A0 and vary the PWM based on A0. Then if Digital 5 is turned off over canbus, then it turns the signal completely off.

Attached is the sketch that is an example from the software that I've edited and I think the relivant section is going to be "void HandleIncomingSetValueFrame" that would handle this difference with D5. Thanks for the help guys.

// Arduino digital and analog pins
// digital pin statuses are stored as bits in one variable
unsigned int digitalPins = 0;
// analog pin values are stored in array of ints
int analogPins[7] = {0};

unsigned int rpm = 0;
unsigned int kpa = 992; // 99.2
unsigned int tps = 965; // 96.5
unsigned int clt = 80;  // 80 - 100
unsigned int textCounter = 0;

// incoming data
byte incomingFrame[17] = { 0 };
unsigned int incomingFramePos = 0;

// if READWRITE_PINS is defined, the values are read from and written to Arduino
// digital and analog pins.
#define READWRITE_PINS

void setup()
{
  #if defined (READWRITE_PINS)
  // set digital pins as outputs
  for (int i=1; i<14; i++)
  {
    pinMode(i, OUTPUT);
  }
  #endif

  // init serial
  Serial.begin(115200);
  delay(100);
}


void loop()
{
  ReadDigitalStatuses();
  ReadAnalogStatuses();
  SendCANFramesToSerial();
  ReadIncomingSerialData();

  
  /*
  // just some dummy values for simulated engine parameters
  if (rpm++ > 10000)
  {
    rpm = 500;
  }
  if (kpa++ > 2500)
  {
    kpa = 10;
  }
  if (tps++ > 1000)
  {
    tps = 0;
  }
  if (clt++ > 230)
  {
    // all values in frame are handled as unsigned values. To use negative values,
    // offset actual value and write corresponding conversion to XML file imported to RealDash
    // From RealDash 1.7.6 its also possible to specify value as signed="true" in XML file.
    clt = 0;
  }
  */
  // simple counter for sending the text frame to avoid sending it too often.
  if (textCounter++ > 4000)
  {
    textCounter = 0;
  }
  //DigitalTest();
  //AnalogTest();
  delay(5);
}



void DigitalTest()
{
  for (int i=1; i<14; i++)
  {
    Serial.print("Digital Output ");
    Serial.println(i);
    Serial.println(digitalRead(i));
    delay(1000);
  }
}

void ReadDigitalStatuses()
{
#if defined (READWRITE_PINS)
  // read status of digital pins (1-13)
  digitalPins = 0;

  int bitposition = 0;
  for (int i=1; i<14; i++)
  {
    if (digitalRead(i) == HIGH) digitalPins |= (1 << bitposition);
    bitposition++;
    //Serial.print("Digital Output ");
    //Serial.println(i);
    //Serial.println(digitalRead(i));
    //Serial.print("Bitposition ");
    //Serial.println(bitposition);
    //Serial.println("Digital Pins Value ");
    //Serial.println(digitalPins);
    //delay(1000);
  }
#endif
}

void AnalogTest()
{
  for (int i=0; i<7; i++)
  {
    Serial.print("Analog Output ");
    Serial.println(i);
    Serial.println(analogRead(i));
    delay(1000);
  }
}

void ReadAnalogStatuses()
{
#if defined (READWRITE_PINS)
  // read analog pins (0-7)
  for (int i=0; i<7; i++)
  {
    analogPins[i] = analogRead(i);
  }
#endif
}


void SendCANFramesToSerial()
{
  byte frameData[8];

  // build & send CAN frames to RealDash.
  // a CAN frame payload is always 8 bytes containing data in a manner
  // described by the RealDash custom channel description XML file
  // all multibyte values are handled as little endian by default.
  // endianess of the values can be specified in XML file if it is required to use big endian values

  // build 1st CAN frame, RPM, MAP, CLT, TPS (just example data)
  memcpy(frameData, &rpm, 2);
  memcpy(frameData + 2, &kpa, 2);
  memcpy(frameData + 4, &clt, 2);
  memcpy(frameData + 6, &tps, 2);

  // write first CAN frame to serial
  SendCANFrameToSerial(3200, frameData);

  // build 2nd CAN frame, Arduino digital pins and 2 analog values
  memcpy(frameData, &digitalPins, 2);
  memcpy(frameData + 2, &analogPins[0], 2);
  memcpy(frameData + 4, &analogPins[1], 2);
  memcpy(frameData + 6, &analogPins[2], 2);

  // write 2nd CAN frame to serial
  SendCANFrameToSerial(3201, frameData);

  // build 3rd CAN frame, rest of Arduino analog values
  memcpy(frameData, &analogPins[3], 2);
  memcpy(frameData + 2, &analogPins[4], 2);
  memcpy(frameData + 4, &analogPins[5], 2);
  memcpy(frameData + 6, &analogPins[6], 2);

  // write 3rd CAN frame to serial
  SendCANFrameToSerial(3202, frameData);

  // build 4th frame, this is a text extension frame
  // only send once at 1000 loops
  if (textCounter == 0)
  {
    SendTextExtensionFrameToSerial(3203, "Hello RealDash, this is Arduino sending some text data");
  }
  else if (textCounter == 1000)
  {
    SendTextExtensionFrameToSerial(3203, "Tomorrow's forecast: Lots of sun and 30 degrees centigate");
  }
  else if (textCounter == 2000)
  {
    SendTextExtensionFrameToSerial(3203, "Now Playing: Insert your favorite song info here");
  }
  else if (textCounter == 3000)
  {
    SendTextExtensionFrameToSerial(3203, "Message from Arduino: All systems running at nominal efficiency");
  }
}


void SendCANFrameToSerial(unsigned long canFrameId, const byte* frameData)
{
  // the 4 byte identifier at the beginning of each CAN frame
  // this is required for RealDash to 'catch-up' on ongoing stream of CAN frames
  const byte serialBlockTag[4] = { 0x44, 0x33, 0x22, 0x11 };
  Serial.write(serialBlockTag, 4);

  // the CAN frame id number (as 32bit little endian value)
  Serial.write((const byte*)&canFrameId, 4);

  // CAN frame payload
  Serial.write(frameData, 8);
}


void SendTextExtensionFrameToSerial(unsigned long canFrameId, const char* text)
{
  if (text)
  {
    // the 4 byte identifier at the beginning of each CAN frame
    // this is required for RealDash to 'catch-up' on ongoing stream of CAN frames
    const byte textExtensionBlockTag[4] = { 0x55, 0x33, 0x22, 0x11 };
    Serial.write(textExtensionBlockTag, 4);

    // the CAN frame id number (as 32bit little endian value)
    Serial.write((const byte*)&canFrameId, 4);

    // text payload
    Serial.write(text, strlen(text) + 1);
  }
}


void ReadIncomingSerialData()
{
  while (Serial.available() > 0)
  {
    // little bit of extra effort here, since especially Bluetooth connections
    // may leave unsent/received data in internal buffer for a long time
    // therefore, we cannot be sure that incoming byte stream really starts at
    // where we expect it to start.

    // read one byte from serial stream
    incomingFrame[incomingFramePos++] = Serial.read();

    // check the first incoming bytes tag (0x44, 0x33, 0x22, 0x11)
    if (incomingFrame[0] != 0x44)
    {
      // first incoming byte is not 0x44, 
      // the tag at the beginning of the frame does not match, this is an invalid frame
      // just zero the incomingFrame buffer and start expecting first byte again
      memset(incomingFrame, 0, 17);
      incomingFramePos = 0;
    }

    if (incomingFramePos >= 17)
    {
      // frame complete, process it
      ProcessIncomingFrame(incomingFrame);
      
      // zero the incomingFrame buffer and start expecting first byte again
      memset(incomingFrame, 0, 17);
      incomingFramePos = 0;
    }
  }
}


void ProcessIncomingFrame(const byte* frame)
{
  // first four bytes contain set value frame separator bytes, always 0x44,0x33,0x22,x11
  // check that first 4 bytes match the tag
  if (frame[0] != 0x44 ||
      frame[1] != 0x33 ||
      frame[2] != 0x22 ||
      frame[3] != 0x11)
  {
    // frame tag does not match, wait for another frame
    return;
  }

  // next four bytes contain set value CAN frame id in little endian form
  unsigned long canFrameId = 0;
  memcpy(&canFrameId, frame + 4, 4);

  // next 8 bytes are the frame data
  // ...
  
  // last byte is check byte calculated as sum of previous 13 bytes (ignore overflow)
  byte checkByte = 0;
  for (int i=0; i<16; i++)
  {
    checkByte += frame[i];
  }

  if (frame[16] == checkByte)
  {
    // checksum match, this is a valid set value-frame:
    // the frame payload data is in frame + 8 bytes
    HandleIncomingSetValueFrame(canFrameId, frame + 8);
  }
}


void HandleIncomingSetValueFrame(unsigned long canFrameId, const byte* frameData)
{
  if (canFrameId == 3201)
  {
    memcpy(&digitalPins, frameData, 2);
    memcpy(&analogPins[0], frameData + 2, 2);
    memcpy(&analogPins[1], frameData + 4, 2);
    memcpy(&analogPins[2], frameData + 6, 2);
    
#if defined (READWRITE_PINS)
    // write digital pins
    for (int i=0; i<13; i++)
    {
      if (i==4)
      {
       if ((digitalPins & (1 << i)) == HIGH)
       {
        int output;
        int led_value;
        output = analogRead(A0);
        led_value = map(output, 0, 1023, 255, 120);
        analogWrite(i + 1, led_value);  
       }
       //else if ((digitalPins & (1 << i)) != HIGH)
       //{
       // digitalWrite(i + 1, (digitalPins & (1 << i)) ? HIGH : LOW);
       //}
      }
      else if (i != 4)
      {
      digitalWrite(i + 1, (digitalPins & (1 << i)) ? HIGH : LOW);
      }
    }
    
    analogWrite(0, analogPins[0]);
    analogWrite(1, analogPins[1]);
    analogWrite(2, analogPins[2]);
#endif
  }
  else if (canFrameId == 3202)
  {
    memcpy(&analogPins[3], frameData + 0, 2);
    memcpy(&analogPins[4], frameData + 2, 2);
    memcpy(&analogPins[5], frameData + 4, 2);
    memcpy(&analogPins[6], frameData + 6, 2);
    
#if defined (READWRITE_PINS)
    analogWrite(3, analogPins[3]);
    analogWrite(4, analogPins[4]);
    analogWrite(5, analogPins[5]);
    analogWrite(6, analogPins[6]);
#endif
  }
}

I am having a hard time following what you are asking. What is digital 5, 1 input? Posting a Schematic showing how you have it wired, not a frizzy picture will help us help you a lot. Even more help would be links to the external hardware. Not all pins on the nano support PWM (software PWM excepted),

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.