XirallicBolts

Flex - Sync 3 Video in Motion

Oct 23rd, 2021 (edited)
175
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //  XirallicBolts
  2. //  Sync 3 Video-in-Motion for Ford Flex
  3. //  
  4. //  Not compatible with vehicles equipped with multiple cameras
  5. //  
  6. //  Front camera display using Shift Knob +
  7. //  Toggle front/rear camera using Shift Knob -
  8. //  Activate driver heated seat / steering wheel using Eject
  9. //  
  10. //  9-4-2021  Found proper IPMB message, activate at speed
  11. //  
  12. //  Arduino Connections
  13. //  INT     2       Pink / Brown
  14. //  Relay   6       Green
  15. //  Shift+  8       Grey
  16. //  Shift-  9       Grey / White
  17. //  CS      10      White / Pink
  18. //  S1      11      White
  19. //  S0      12      Yellow
  20. //  SCK     13      Purple
  21. //
  22. //  --------------------------------
  23. //
  24. //  HS3-CAN +         Orange
  25. //  HS3-CAN -         White / Orange
  26. //  Acc 12v           Red
  27. //  Ground            White / Red
  28. //
  29. //  --------------------------------
  30. //    
  31. //  Message ID 0x109   Data:  00 00 00 00 00 00 00 00
  32. //                            ^^ ^^                     RPM (Hex, multiplied by 4)
  33. //                                  ^                   Gear (0 Park | 1 Reverse | 2 Neutral | 3 Drive | 4 Sport)
  34. //                                     ^^ ^^ ^^         Vehicle Speed
  35. //                                              ^       Ignition Mode? (2 Accessory | 5 Engine Running)
  36. //
  37. //
  38. //  Message ID 0x2A0   xx FF FF FF 10 00 1E 02     Button is PRESSED
  39. //  (Front Panel)      xx FF FF FF 10 00 1E 00     Button is HELD
  40. //                     xx FF FF FF 00 00 1E 00     Button is RELEASED
  41. //                     0x34: Eject         0x18: Sound       0x5F: Home     0x1F: Power
  42. //
  43. //  Message ID 0x35B   00 00 00 FE 80 00 00        Heated Steering Wheel
  44. //  (Climate)          00 00 01 FE 00 00 00        Driver Heated Seat
  45. //                     00 00 03 FE 00 00 00        Passenger Heated Seat
  46. //
  47. //  Message ID 0x3EE   00 08 08 1B 80 00 00 00     Request camera display
  48. //  (Image Processor)  00 00 08 1B 80 00 00 00     Cancel camera display
  49. //
  50. // Common between shift buttons connects to ground
  51. //  
  52. // CAN0.sendMsgBuf(message_ID, 0, message_LENGTH, message_DATA);
  53.  
  54.  
  55. #include <mcp_can.h>
  56. #include <SPI.h>
  57. #define CAN_INT         2
  58. #define CAN_CS          10
  59. #define CAMERA_RELAY    7     // Trigger pin on DPDT relay
  60. #define BUTTON_REQUEST  8     // Request Camera button. Connect to Ground to signal.
  61. #define BUTTON_TOGGLE   9     // Toggle front/rear camera button. Connect to Ground to signal.
  62.  
  63. MCP_CAN CAN0(CAN_CS);
  64.  
  65. byte ForceRearCamera         = 0;    // If the car is in reverse, forcibly switch to rear camera
  66. byte CameraRequestButtonHeld = 0;
  67. byte CameraToggleButtonHeld  = 0;
  68. byte CameraButtonReleased    = 0;    // Camera Request button was released, attempt to display camera if conditions are right
  69. byte CurrentGear             = 0;    // Every time 0x109 comes through, take note of current gear
  70. byte CameraViewActive        = 0;    // Are we currently in a camera view?
  71. byte HeatedSeatButtonHeld    = 0;    // Counter to track how long a given button (Eject in my case) is being held
  72. String PendingMessage      = "none";
  73. String LastMessage         = "none";
  74.  
  75. long unsigned int message_ID;
  76. unsigned char message_LENGTH = 0;
  77. unsigned char message_DATA[8];
  78. unsigned char message_Camera_Request[8] = {0x00, 0x08, 0x08, 0x1B, 0x80, 0x00, 0x00, 0x00};
  79. unsigned char message_Camera_Cancel[8] = {0x00, 0x00, 0x08, 0x1B, 0x80, 0x00, 0x00, 0x00};
  80. unsigned char message_Fake_Speed[8] = {0x09, 0x13, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00};
  81. unsigned char message_Heated_Seat_Driver[8] = {0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00};
  82. unsigned char message_Heated_Seat_Passenger[8] = {0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00};
  83. unsigned char message_Heated_Wheel[8] = {0x00, 0x00, 0x00, 0xFE, 0x80, 0x00, 0x00, 0x00};
  84.  
  85.  
  86. void setup() {
  87.   pinMode(CAMERA_RELAY, OUTPUT);
  88.   pinMode(BUTTON_REQUEST, INPUT_PULLUP);
  89.   pinMode(BUTTON_TOGGLE, INPUT_PULLUP);
  90.   pinMode(CAN_INT, INPUT);
  91.   digitalWrite(CAMERA_RELAY, HIGH);   // Default to front camera
  92.  
  93.   Serial.begin(115200);
  94.     Serial.println("XirallicBolts");
  95.     Serial.println("Front Camera and Video-in-Motion");
  96.     Serial.println("-------");
  97.  
  98.   if(CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
  99.     Serial.println("MCP2515 Initialized Succesfully");
  100.   else
  101.     Serial.println("Could not initialize MCP2515 (CS 10, INT 2, 500KBPS, 16MHz");  
  102.  
  103.   // Immediately send a Camera Cancel in case something got stuck on the last ignition cycle
  104.   CAN0.setMode(MCP_NORMAL);
  105.   CAN0.sendMsgBuf(0x3EE, 0, message_LENGTH, message_Camera_Cancel);
  106. }
  107.  
  108. void loop() {
  109.  
  110.   if(!digitalRead(CAN_INT))
  111.   {
  112.     CAN0.readMsgBuf(&message_ID, &message_LENGTH, message_DATA);
  113.  
  114.  
  115.  
  116.  
  117.     // Send a "Camera Cancel" if the car is shifted into Park
  118.     // Store the Current Gear for other uses.
  119.     if(message_ID == 0x109)
  120.     {
  121.       if((message_DATA[2] <= 0x0F) && (CurrentGear >= 0x10))
  122.       {
  123.         CAN0.sendMsgBuf(0x3EE, 0, message_LENGTH, message_Camera_Cancel);
  124.         CameraViewActive = 0;
  125.         Serial.println("Vehicle shifted to Park. Canceling camera");
  126.       }
  127.       CurrentGear = message_DATA[2];
  128.     }
  129.  
  130.  
  131.  
  132.  
  133.     // If the car is in Reverse (or Forced Rear), toggle rear camera.
  134.     if(((CurrentGear >= 0x10) && (CurrentGear <= 0x1F)) || (ForceRearCamera == 1))
  135.     {
  136.       if(ForceRearCamera == 1)
  137.         PendingMessage = "Rear camera forced by button press";
  138.       else
  139.         PendingMessage = "Rear camera forced by current gear";
  140.       digitalWrite(CAMERA_RELAY, LOW);
  141.     }
  142.  
  143.  
  144.  
  145.  
  146.     // If the car is NOT in Reverse or Forced Rear, toggle front camera.
  147.     if(((CurrentGear <= 0x0F) || (CurrentGear >= 0x20)) && (ForceRearCamera == 0))
  148.     {
  149.       PendingMessage = "Front camera selected (Vehicle not in reverse, no manual request)";
  150.       digitalWrite(CAMERA_RELAY, HIGH);
  151.     }
  152.  
  153.  
  154.  
  155.  
  156.  
  157.     // If the Camera Request is pressed and not in Camera View, request the camera.
  158.     if((CameraButtonReleased == 1) && (CameraViewActive == 0))
  159.     {
  160.       Serial.println("\nFront camera has been requested.");
  161.       if(CurrentGear != 0x01)
  162.       {
  163.         Serial.println("Vehicle is not in Park.  Sending a falsified speed message...");
  164.         CAN0.sendMsgBuf(0x109, 0, message_LENGTH, message_Fake_Speed);
  165.       }
  166.       Serial.println("Sending Camera Request...");
  167.       CAN0.sendMsgBuf(0x3EE, 0, message_LENGTH, message_Camera_Request);
  168.       CameraButtonReleased = 0;
  169.       CameraViewActive = 1;
  170.     }
  171.  
  172.  
  173.  
  174.  
  175.     // If the Camera Request is pressed and currently in Camera View,  cancel the camera.
  176.     if((CameraButtonReleased == 1) && (CameraViewActive == 1))
  177.     {
  178.       Serial.println("\nCamera CANCEL Requested");
  179.       CAN0.sendMsgBuf(0x3EE, 0, message_LENGTH, message_Camera_Cancel);
  180.       CameraButtonReleased = 0;
  181.       CameraViewActive = 0;
  182.     }
  183.  
  184.  
  185.  
  186.  
  187.     // =======================================================================================
  188.     //
  189.     // Check for Eject button press for heated seat / steering wheel.
  190.     // Increment the counter each time it's seen.
  191.     //
  192.     if(message_ID == 0x2A0 and message_DATA[0] == 0x34 and message_DATA[4] == 0x10)
  193.     {
  194.       Serial.println("Eject button is pressed or held");
  195.       HeatedSeatButtonHeld++;
  196.     }
  197.  
  198.     // Check if Eject button was released.
  199.     if(message_ID == 0x2A0 and message_DATA[0] == 0x34 and message_DATA[4] == 0x10)
  200.     {
  201.       Serial.println("Eject button was released");
  202.       if(HeatedSeatButtonHeld >= 3)
  203.       {
  204.         Serial.println("+ Requesting heated seat (Driver)");
  205.         CAN0.sendMsgBuf(0x35E, 0, 8, message_Heated_Seat_Driver);
  206.         delay(100);
  207.         Serial.println("+ Requesting heated steering wheel");
  208.         CAN0.sendMsgBuf(0x35E, 0, 8, message_Heated_Wheel);
  209.       }
  210.  
  211.       // Regardless of outcome, reset the counter
  212.       HeatedSeatButtonHeld = 0;
  213.     }
  214.   }
  215.  
  216.  
  217.  
  218.  
  219.  
  220. // ===========================================================================================
  221. //
  222. //  Input Triggers
  223. //  Monitor the Request and Toggle inputs
  224. //
  225.  
  226.   // Check if the button is currently being pressed (Pin connected to ground)
  227.   if(digitalRead(BUTTON_REQUEST) == LOW)
  228.   {  
  229.     CameraRequestButtonHeld = 1;
  230.   }
  231.   if(digitalRead(BUTTON_TOGGLE) == LOW)
  232.   {
  233.     CameraToggleButtonHeld = 1;
  234.   }
  235.  
  236.   // React if a pressed button has been released.
  237.   if(digitalRead(BUTTON_REQUEST) == HIGH and CameraRequestButtonHeld == 1)
  238.   {
  239.     Serial.println("\nCamera Request has been released.\n");
  240.     CameraRequestButtonHeld = 0;
  241.     CameraButtonReleased = 1;
  242.   }
  243.  
  244.   if(digitalRead(BUTTON_TOGGLE) == HIGH and CameraToggleButtonHeld == 1)
  245.   {
  246.     Serial.println("\nCamera Toggle has been released.\n");
  247.     CameraToggleButtonHeld = 0;
  248.     ForceRearCamera = !ForceRearCamera;
  249.   }
  250.  
  251.  
  252.  
  253. // ===========================================================================================
  254.  
  255.  
  256.  
  257. // If there's a pending message and it's NOT a duplicate of the last message, broadcast it.
  258. // Only used for messages that tend to repeat, to help keep SerialMonitor clean.
  259.   if((PendingMessage != "none") && (PendingMessage != LastMessage))
  260.   {
  261.     Serial.println(PendingMessage);
  262.     LastMessage = PendingMessage;
  263.     PendingMessage = "none";
  264.   }
  265.  
  266. }
RAW Paste Data