ข่าวประชาสัมพันธ์

มาร่วมเป็นกำลังใจให้เว็บด้วยการสมัครสมาชิกวีไอพี ~~ เลือกปีที่ท่านต้องการได้โดยไม่ต้องเรียงปี ~~ ปีละ 350 บาท สมัคร 2 ปีลดเหลือ 600 บาท ~~ มีไลน์กลุ่ม VIP จำนวนหลายร้อยท่าน เอาไว้ปรึกษางานซ่อม ~~ เข้าถึงข้อมูลด้านเทคนิค ข้อมูลเชิงลึกมากมาย.....


ผู้เขียน หัวข้อ: สื่อสารระหว่างบอร์ด arduino หรือ Esp ผ่านสายยาวๆ ด้วย CAN bus  (อ่าน 1157 ครั้ง)

0 สมาชิก และ 1 บุคคลทั่วไป กำลังดูหัวข้อนี้

ออฟไลน์ Auto Man

  • Administrator
  • หัวหน้าศูนย์ซ่อมสร้าง
  • *****
  • เจ้าของกระทู้
  • Joined: ก.ย. 2558
  • กระทู้: 37161
  • สมาชิกลำดับที่ : 1
  • เพศ: ชาย
  • มือผู้ให้ย่อมสูงกว่ามือผู้รับ
    • เว็บชุมชนคนรักช่างยนต์
    • อีเมล์
   สื่อสารระหว่างบอร์ด arduino หรือ Esp ผ่านสายยาวๆ ด้วย CAN bus โดยใช้โมดูล MCP2515   
    พอดีไปเจอบทความในเว็บที่เกี่ยวกับการสื่อสารแบบ Can bus เลยนำมาไว้ที่นี่ ขอบคุณเจ้าของบทความครับ

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


มาเริ่มกันเลย

สวัสดีครับ ในการสร้างยานพาหนะคันนึง มักประสบปัญหาทางการสื่อสารระหว่างอุปกรณ์ที่มีระยะระหว่างอุปกรณ์ยาวๆ
มากกว่า 2 เมตรขึ้นไป การสื่อสารโดยใช้ I2C หรือ SPI หรือ Uart มักประสบปัญหาเรื่องแรงดันที่ลดลงเมื่อระยะทางที่มากขึ้น
ทำให้การแปลงค่าเป็น logic ต่างๆไม่สมบูรณ์ เช่น

ฝั่งส่ง ส่งไป 5v (logic HIGH) สายไฟที่ใช้อาจจะเป็นสายเส้นเล็กเกินไปทำให้แรงดันไฟตกเหลือแค่ 3.8v
ซึ่งอาจไม่พอที่จะทำให้ฝ่ายรับเข้าใจว่าเป็น logic HIGH ทำให้การสื่อสารไม่สมบูรณ์


CAN bus จึงเปลี่ยนวิธีการอิงจาก 0v เป็นอิงจาก "ผลต่างแรงดันระหว่างสายสองเส้น" โดยสายสองเส้นเรียกว่า CAN High และ CAN Low
โดยปกติทั้งสองเส้นจะมีแรงดันที่ 2.5v เมื่อมีการส่งข้อมูล สายที่เป็น CAN High จะมีแรงดันเพิ่มขึ้นเป็น 3.75V และสายที่เป็น CAN Low
จะมีแรงดันลดลงเป็น 1.25V เมื่อคิดแรงดันผลต่างระหว่างเส้น จะกลายเป็น 2.5V ดังรูป

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


แล้วมันแก้ปัญหาเรื่องระยะทางอย่างไรล่ะ? คือเมื่อสายแต่ละเส้นมีแรงดันที่ลดลงจากระยะทางที่มากขึ้นของสายไฟ
เช่น ลดลงไป 1.2v เท่าๆกัน CAN High จะเหลือ 2.55 CAN Low จะเหลือ 0.05V ผลต่างแรงดันทั้งคู่ก็ยังคงเป็น 2.5V เท่าเดิม

มาลองดูความยาวสายไฟที่ CAN Bus สามารถทำได้กัน จะเห็นว่าที่ความถี่ข้อมูลต่ำๆ สามารถส่งไปได้ไกลถึง 1000m เลยทีเดียว
ซึ่งเมื่อเทียบกับ I2C bus ที่ให้ความเร็วที่ 100Kbps ที่ 1m และ 10Kbps ที่ 10m เท่านั้นเอง

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


นอกจากข้อดีเรื่องระยะความยาวสายไฟที่เหนือกว่าการสื่อสารแบบ I2C CAN bus ยังมีความสามารถสื่อสารระหว่างอุปกรณ์ใดๆ
โดยทุกอุปกรณ์สามารถเป็นได้ทั้ง Master และ Slave ในตัวเดียวกัน ซึ่งแต่ละอุปกรณ์จะกรองข้อมูลที่วิ่งผ่านสาย CAN bus
เพื่อนำไปใช้ประโยชน์เท่าที่ตัวเองต้องการ และยังมีระบบป้องกันการชนกันของข้อมูลด้วยการจัดลำดับความสำคัญของข้อมูลนั้นๆ
ทำให้มั่นใจได้ว่าข้อมูลถูกส่งไปอย่างถูกต้อง


รูปด้านล่างแสดงให้เห็นว่า จากเดิมเมื่ออุปกรณ์แต่ละอุปกรณ์ต้องสื่อสารกัน การใช้ CAN Bus ช่วยลดความยาวสายไฟ
จากการใช้สายไฟร่วมกันได้อย่างง่ายดาย

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


ในบทความนี้จะสาธิตการใช้ CAN Bus กับ Arduino สองบอร์ด เพื่อส่งตัวเลขกันครับ แต่เนื่องจาก Arduino เดิมๆ
ไม่สามารถสื่อสารด้วย CAN Bus ได้ เพราะมีแต่ I2C/Uart/SPI โมดูล MCP2515 จึงถูกใช้เป็นสื่อการที่แปลง SPI
 เป็น CAN bus โดยโมดูลตัวนี้จะรองรับ CAN protocal เวอร์ชัน 2.0B สามารถสื่อสารได้เร็วถึง 1Mbps

โมดูล MCP2515 ภายในจะมี ic ย่อยอยู่ 2 ตัว คือ MCP2515 ic ทำหน้าที่รับ SPI แปลงเป็น Uart ส่งต่อให้
TJA1050 ic ที่ทำหน้าที่แปลง Uart เป็น CAN bus ดังรูปด้านล่าง

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


รายละเอียดแค่พอประมาณ learning by doing กันเลยดีกว่า โดยการต่อวงจรระหว่าง Arduino และ MCP2515 มีอุปกรณ์ต่างๆที่ใช้ดังนี้

อุปกรณ์ที่ใช้

1. Arduino Nano 3.0 ใช้ชิฟ CH340G แถมสาย mini usb x2
2. breadboard 830 hole MB-102 บอร์ดทดลองแบบใส 830รู
3. ชุดสายไฟสำหรับต่อวงจร 140 เส้น breadboard jumper boxed 140 peices
4. โมดูลแปลง CAN bus เป็น SPI bus MCP2515 SPI CAN Bus Controller and Driver Module


โดยให้เราต่อวงจรตามรูปด้านล่าง เราจะแบ่งส่วนตัวส่งกับตัวรับกันดังรูป

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


ตามวงจรด้านบน หน้าตาก็จะประมาณนี้ ถ้าใครมี Oscilloscope ลองจับตรงขา CAN high และ CAN low
บน โมดูล MCP2515 ของ Arduino ฝั่งรับเพื่อจับสัญญาณที่มันได้มาจาก Arduino ฝั่งส่งดูครับ

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


ในส่วนของโปรแกรม ให้เราโหลดไลบรารี่สำหรับโมดูลนี้ได้จาก Library manager ชื่อ CAN_BUS_SHIELD

หรือผ่านลิ้ง

https://github.com/Seeed-Studio/CAN_BUS_Shield


จากนั้นให้อัพโหลด Code ตามArduino ที่เราแยกฝั่งส่งฝั่งรับลงไป

โค๊ดฝั่งตัวส่ง
โค๊ด: [Select]
#include <SPI.h>
#include <mcp_can.h>

const int spiCSPin = 10;
int ledHIGH    = 1;
int ledLOW     = 0;

MCP_CAN CAN(spiCSPin);

void setup()
{
    Serial.begin(115200);

    while (CAN_OK != CAN.begin(CAN_500KBPS))
    {
        Serial.println("CAN BUS init Failed");
        delay(100);
    }
    Serial.println("CAN BUS Shield Init OK!");
}

unsigned char stmp[8] = {ledHIGH, 1, 2, 3, ledLOW, 5, 6, 7};
   
void loop()
{   
  Serial.println("In loop");
  CAN.sendMsgBuf(0x43, 0, 8, stmp);
  delay(1000);
}

Code ฝั่งรับ
โค๊ด: [Select]
#include <SPI.h>
#include "mcp_can.h"

const int spiCSPin = 10;
const int ledPin = 2;
boolean ledON = 1;

MCP_CAN CAN(spiCSPin);

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

    while (CAN_OK != CAN.begin(CAN_500KBPS))
    {
        Serial.println("CAN BUS Init Failed");
        delay(100);
    }
    Serial.println("CAN BUS  Init OK!");
}


void loop()
{
    unsigned char len = 0;
    unsigned char buf[8];

    if(CAN_MSGAVAIL == CAN.checkReceive())
    {
        CAN.readMsgBuf(&len, buf);

        unsigned long canId = CAN.getCanId();

        Serial.println("-----------------------------");
        Serial.print("Data from ID: 0x");
        Serial.println(canId, HEX);

        for(int i = 0; i<len; i++)
        {
            Serial.print(buf[i]);
            Serial.print("\t");
            if(ledON && i==0)
            {

                digitalWrite(ledPin, buf[i]);
                ledON = 0;
                delay(500);
            }
            else if((!(ledON)) && i==4)
            {

                digitalWrite(ledPin, buf[i]);
                ledON = 1;
            }
        }
        Serial.println();
    }
}

เมื่อลองใช้ Oscilloscope จะพบว่า CAN bus มีข้อมูลวิ่งในสายพร้อมใช้งานแล้ว

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


เมื่อเปิด Serial monitor เราจะเห็นว่าฝั่งรับมีข้อมูลเข้ามา 8 byte ซึ่งเป็นปกตืของ CAN bus ที่สามารถส่งข้อมูลได้ตั้งแต่ 0-8 byte
โดยให้ผู้อ่านลองเล่นกับค่าตัวส่งให้ส่งข้อมูลเป็นตัวอักษรหรือค่าอื่นๆ และลองเพิ่มตัวส่งหรือตัวรับ และลองเปลี่ยน ID จาก 0x00
เป็นค่าอื่นตั้งแต่ 0-2047 ดูโดยไม่จำเป็นต้องไปวุ่นวายกับ protocal เลย หน้าที่นั้น โมดูล MCP2515 เป็นตัวจัดการให้เสร็จสรรพ
หน้าที่เราแค่เพียงใส่ id กับ ข้อมูล เท่านั้นเองครับ

แต่หากใครมีปัญหาเรื่องสัญญาณหรี่ออกมาแบบนี้ จะเกิดจากตัวต้านทานปลาย terminal ไม่ถูกใส่อย่างถูกต้อง (รายละเอียดขอละไว้)

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


แต่โมดูล MCP2515 มีจั้มเปอร์ให้ต่อเพื่อใส่ตัวต้านทานมาให้เสร็จสรรพ เพียงแค่ต่อjumper (หรือบัดกรีเข้าหากัน)
ก็แก้ปัญหาเรื่องสัญญาณเพี้ยนได้ทันที

ตรงนี้มีภาพ! แต่ท่านจะมองไม่เห็น , ท่านต้อง  สมัครสมาชิก หรือ ลงชื่อเข้าระบบ


หวังว่าบทความนี้จะจุดประกายไอเดียการสื่อสารระหว่างอุปกรณ์บางอย่างให้ผู้อ่านไม่มากก็น้อย


ธนบดี บุหลันศรีชาติ
ผู้เขียน

Reference
https://www.electronicshub.org/arduino-mcp2515-can-bus-tutorial/
http://www.can-wiki.info/doku.php?id=can_faq:can_cabling
http://www.mosaic-industries.com/embedded-systems/sbc-single-board-computers/freescale-hcs12-9s12-c-language/instrument-control/i2c-bus-specifications
https://www.axiomatic.com/whatiscan.pdf

   ข้อมูลมาจาก ที่นี่....
« แก้ไขครั้งสุดท้าย: 08 กรกฎาคม 2564, 06:35:52 โดย Auto Man »
สวัสดีคุณ...ผู้เยี่ยมชม  กด ❤ ถูกใจโพสท์นี้ หรือยัง...
ต้องการสมัครสมาชิก VIP สมัครได้ที่นี่...   หรือทาง Line ID: k.sonchai