class CAN – אפיק תקשורת רשת בקרים (controller area network)¶
CAN מממש תמיכה הן ב-CAN קלאסי (bxCAN, בשימוש ב-OpenMV Cam M4 ו-M7) והן ב-CAN FD (FDCAN, בשימוש ב-OpenMV Cam H7, H7 Plus ו-Pure Thermal). ברמה הפיזית אפיק ה-CAN מורכב משני קווים, RX ו-TX. כדי לחבר OpenMV Cam לאפיק CAN עליך להשתמש במשדר-מקלט CAN (transceiver) כדי להמיר את אותות הלוגיקה של ה-CAN מה-MCU לרמות המתח הנכונות באפיק.
CAN קלאסי במצב לולאה חוזרת (loopback, ללא transceiver):
from pyb import CAN
can = CAN(1, CAN.LOOPBACK)
# Accept messages with id 123, 124, 125 or 126.
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))
can.send("message!", 123) # send a message with id 123
can.recv(0) # receive a message on FIFO 0
CAN FD עם כל המאפיינים האופציונליים מופעלים (FD frame, מיתוג קצב סיביות, מזהי פריים מורחבים; שלב arbitration של 500 kbit/s, שלב נתונים של 1 Mbit/s):
from pyb import CAN
can = CAN(
1,
CAN.NORMAL,
baudrate=500_000,
brs_baudrate=1_000_000,
sample_point=80,
)
# Accept any id in the range 0xFFF0 .. 0xFFFF.
can.setfilter(0, CAN.RANGE, 0, (0xFFF0, 0xFFFF))
can.send(b"a" * 64, 0xFFFF, fdf=True, brs=True, extframe=True)
can.recv(0)
פונקציות מודול ה-CAN הבאות והארגומנטים שלהן זמינות הן עבור בקרי CAN קלאסי והן עבור בקרי FD, אלא אם צוין אחרת.
בנאים (Constructors)¶
- class pyb.CAN(bus: int | str, *args, **kwargs)¶
בונה אובייקט CAN על ה-
busהנתון (אינדקס התקן היקפי מסוג מספר שלם, למשל1עבורCAN1,2עבורCAN2). ללא פרמטרים נוספים האובייקט נוצר אך אינו מאותחל (הוא שומר על הגדרות האפיק הקודמות, אם קיימות); אם ניתנים ארגומנטים נוספים האפיק מאותחל. ראהCAN.init()עבור הפרמטרים הזמינים.CAN(2)מחווט לאותם פיני מחבר (header) בכל OpenMV Cam שחושף אתpyb.CAN(M4 / M7 / H7 / H7 Plus / Pure Thermal):אות
פין מחבר
הערות
RXP3TXP2ההתקן ההיקפי CAN מספק אותות ברמת לוגיקה בלבד; נדרש משדר-מקלט CAN (transceiver) חיצוני כדי להניע אפיק CAN אמיתי.
pyb.CANאינו זמין ב-OpenMV Cam N6.שיטות (Methods)¶
- init(mode: int, prescaler: int = 100, *, sjw: int = 1, bs1: int = 6, bs2: int = 8, auto_restart: bool = False, baudrate: int = 0, sample_point: int = 75, num_filter_banks: int = 14, brs_sjw: int = 1, brs_bs1: int = 8, brs_bs2: int = 3, brs_baudrate: int = 0, brs_sample_point: int = 75) None¶
מאתחל את אפיק ה-CAN עם הפרמטרים הנתונים:
mode הוא אחד מבין: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
prescaler הוא הערך שבו מחולק שעון הכניסה של ה-CAN כדי לייצר את קוונטות זמן הסיבית הנומינלי. ה-prescaler יכול להיות ערך בין 1 ל-1024 כולל עבור CAN קלאסי, ובין 1 ל-512 כולל עבור CAN FD.
sjw הוא רוחב קפיצת הסנכרון מחדש ביחידות של קוונטות זמן עבור סיביות נומינליות; הוא יכול להיות ערך בין 1 ל-4 כולל עבור CAN קלאסי, ובין 1 ל-128 כולל עבור CAN FD.
bs1 מגדיר את מיקום נקודת הדגימה ביחידות של קוונטות הזמן עבור סיביות נומינליות; הוא יכול להיות ערך בין 1 ל-16 כולל עבור CAN קלאסי, ובין 2 ל-256 כולל עבור CAN FD.
bs2 מגדיר את מיקום נקודת השידור ביחידות של קוונטות הזמן עבור סיביות נומינליות; הוא יכול להיות ערך בין 1 ל-8 כולל עבור CAN קלאסי, ובין 2 ל-128 כולל עבור CAN FD.
auto_restart קובע האם הבקר ינסה אוטומטית להפעיל מחדש את התקשורת לאחר כניסה למצב bus-off; אם זה מושבת אז ניתן להשתמש ב-
restart()כדי לצאת ממצב ה-bus-offbaudrate אם מסופק baudrate שונה מ-0, פונקציה זו תנסה לחשב אוטומטית את זמן הסיבית הנומינלי של ה-CAN (תוך עקיפה של prescaler, bs1 ו-bs2) שמספק הן את ה-baudrate (בתחום של .1%) והן את ה-sample_point הרצוי (לאחוז ה-1% הקרוב ביותר). לשליטה מדויקת יותר על תזמון ה-CAN, הגדר ישירות את הפרמטרים prescaler, bs1 ו-bs2.
sample_point מציין את מיקום דגימת הסיבית ביחס לכל זמן הסיבית הנומינלי, מבוטא כאחוז שלם מזמן הסיבית הנומינלי. ברירת המחדל של sample_point היא 75%. פרמטר זה מתעלם אלא אם baudrate מוגדר.
num_filter_banks עבור CAN קלאסי, זהו מספר הבנקים שיוקצו ל-CAN(1), והשאר מתוך ה-28 יוקצו ל-CAN(2).
הפרמטרים הנותרים קיימים רק בלוחות עם תמיכת CAN FD, ומגדירים את המאפיין האופציונלי Bit Rate Switch (BRS) של CAN FD:
brs_prescaler הוא הערך שבו מחולק שעון הכניסה של ה-CAN FD כדי לייצר את קוונטות זמן סיבית הנתונים. ה-prescaler יכול להיות ערך בין 1 ל-32 כולל.
brs_sjw הוא רוחב קפיצת הסנכרון מחדש ביחידות של קוונטות זמן עבור סיביות נתונים; הוא יכול להיות ערך בין 1 ל-16 כולל
brs_bs1 מגדיר את מיקום נקודת הדגימה ביחידות של קוונטות הזמן עבור סיביות נתונים; הוא יכול להיות ערך בין 1 ל-32 כולל
brs_bs2 מגדיר את מיקום נקודת השידור ביחידות של קוונטות הזמן עבור סיביות נתונים; הוא יכול להיות ערך בין 1 ל-16 כולל
brs_baudrate אם מסופק baudrate שונה מ-0, פונקציה זו תנסה לחשב אוטומטית את זמן סיבית הנתונים של ה-CAN (תוך עקיפה של brs_prescaler, brs_bs1 ו-brs_bs2) שמספק הן את ה-brs_baudrate (בתחום של .1%) והן את ה-brs_sample_point הרצוי (לאחוז ה-1% הקרוב ביותר). לשליטה מדויקת יותר על תזמון ה-BRS, הגדר ישירות את הפרמטרים brs_prescaler, brs_bs1 ו-brs_bs2.
brs_sample_point מציין את מיקום דגימת הסיבית ביחס לכל זמן הסיבית הנומינלי, מבוטא כאחוז שלם מזמן הסיבית הנומינלי. ברירת המחדל של brs_sample_point היא 75%. פרמטר זה מתעלם אלא אם brs_baudrate מוגדר.
קוונטת הזמן tq היא יחידת הזמן הבסיסית עבור אפיק ה-CAN. tq היא ערך ה-prescaler של ה-CAN מחולק ב-PCLK1 (התדר של אפיק ההתקנים ההיקפיים הפנימי 1); ראה
pyb.freq()כדי לקבוע את PCLK1.סיבית בודדת מורכבת מקטע הסנכרון, שהוא תמיד 1 tq. אחריו בא קטע סיבית 1, ואז קטע סיבית 2. נקודת הדגימה היא לאחר שקטע סיבית 1 מסתיים. נקודת השידור היא לאחר שקטע סיבית 2 מסתיים. ה-baud rate יהיה 1/bittime, כאשר ה-bittime הוא 1 + BS1 + BS2 כפול קוונטת הזמן tq.
לדוגמה, ב-OpenMV Cam H7 (PCLK1 = 100 MHz), ניתן להגדיר CAN של 250 kbps עם נקודת דגימה של 75% כ-
prescaler=25, sjw=1, bs1=11, bs2=4:tq = 25 / 100 MHz = 250 ns,bittime = (1 + 11 + 4) × 250 ns = 4 µs, נקודת דגימה =(1 + 11) / 16 = 75%, וה-baudrate הוא1 / 4 µs = 250 kHz.ראה את הסעיף bxCAN / FDCAN במדריך הייחוס של STM32 עבור ה-MCU של ה-OpenMV Cam לפרטים נוספים.
- restart() None¶
מאלץ הפעלה מחדש תוכנתית של בקר ה-CAN ללא איפוס התצורה שלו.
אם הבקר נכנס למצב bus-off אז הוא יפסיק להשתתף בפעילות האפיק. אם הבקר אינו מוגדר להפעלה מחדש אוטומטית (ראה
init()) אז ניתן להשתמש בשיטה זו כדי להפעיל מחדש, והבקר יפעל לפי פרוטוקול ה-CAN כדי לצאת ממצב ה-bus-off ולעבור למצב error active.
- state() int¶
מחזיר את מצב הבקר. ערך ההחזרה יכול להיות אחד מבין:
CAN.STOPPED– הבקר כבוי לחלוטין ומאופס;CAN.ERROR_ACTIVE– הבקר מופעל ובמצב Error Active (גם TEC וגם REC קטנים מ-96);CAN.ERROR_WARNING– הבקר מופעל ובמצב Error Warning (לפחות אחד מבין TEC או REC הוא 96 או יותר);CAN.ERROR_PASSIVE– הבקר מופעל ובמצב Error Passive (לפחות אחד מבין TEC או REC הוא 128 או יותר);CAN.BUS_OFF– הבקר מופעל אך אינו משתתף בפעילות האפיק (TEC עלה על 255).
- info(list: list | None = None) list¶
מקבל מידע על מצבי השגיאה של הבקר ועל חוצצי ה-TX וה-RX. אם list מסופק אז הוא צריך להיות אובייקט רשימה עם לפחות 8 רשומות, שיימולאו במידע. אחרת תיווצר רשימה חדשה ותמולא. בשני המקרים ערך ההחזרה של השיטה הוא הרשימה המאוכלסת.
הערכים ברשימה הם:
ערך TEC
ערך REC
מספר הפעמים שהבקר נכנס למצב Error Warning (מתאפס ל-0 לאחר 65535)
מספר הפעמים שהבקר נכנס למצב Error Passive (מתאפס ל-0 לאחר 65535)
מספר הפעמים שהבקר נכנס למצב Bus Off (מתאפס ל-0 לאחר 65535)
מספר הודעות TX ממתינות
מספר הודעות RX ממתינות ב-fifo 0
מספר הודעות RX ממתינות ב-fifo 1
- setfilter(bank: int, mode: int, fifo: int, params: Tuple[int, ...], *, rtr: Tuple[bool, ...] | None = None, extframe: bool = False) None¶
מגדיר בנק מסננים:
bank הוא בנק המסננים של בקר ה-CAN הקלאסי, או אינדקס מסנן ה-CAN FD, שיש להגדיר.
mode הוא המצב שבו המסנן צריך לפעול, ראה את הטבלאות שלהלן.
fifo הוא איזה fifo (0 או 1) הודעה צריכה להישמר בו, אם היא מתקבלת על ידי מסנן זה.
params הוא מערך של ערכים המגדיר את המסנן. תוכן המערך תלוי בארגומנט mode.
תוכן מערך ה-params עבור בקרי CAN קלאסי (OpenMV Cam M4 / M7):
mode
תוכן params
CAN.LIST16ארבעה מזהים בני 16 סיביות שיתקבלו.
CAN.LIST32שני מזהים בני 32 סיביות שיתקבלו.
CAN.MASK16שני זוגות id/mask בני 16 סיביות, למשל
(1, 3, 4, 4). הזוג הראשון (1, 3) מקבל את כל המזהים עם סיבית 0 = 1 וסיבית 1 = 0; הזוג השני (4, 4) מקבל את כל המזהים עם סיבית 2 = 1.CAN.MASK32זוג id/mask אחד בן 32 סיביות (אחרת זהה ל-
CAN.MASK16).תוכן מערך ה-params עבור בקרי CAN FD (OpenMV Cam H7 / H7 Plus / Pure Thermal):
mode
תוכן params
CAN.RANGEשני מזהים היוצרים טווח של מזהים מתקבלים.
CAN.DUALשני מזהים שיתקבלו (למשל
(1, 2)).CAN.MASKזוג
(id, mask)אחד (למשל(0x111, 0x7FF)).rtr עבור בקרי CAN קלאסי, זהו מערך של ערכים בוליאניים הקובע האם מסנן צריך לקבל הודעת בקשת שידור מרחוק (remote transmission request). אם ארגומנט זה אינו ניתן הוא מקבל כברירת מחדל
Falseעבור כל הרשומות. האורך תלוי ב-mode:mode
len(rtr)הערות
CAN.LIST164
CAN.LIST322
CAN.MASK162
CAN.MASK321
עבור CAN FD ארגומנט זה מתעלם.
extframe אם True לפריים יהיה מזהה מורחב (29 סיביות), אחרת נעשה שימוש במזהה סטנדרטי (11 סיביות).
- clearfilter(bank: int, extframe: bool = False) None¶
מנקה ומשבית בנק מסננים:
bank הוא בנק המסננים של בקר ה-CAN הקלאסי, או אינדקס מסנן ה-CAN FD, שיש לנקות.
extframe עבור בקרי CAN FD, אם True, מנקה מסנן מורחב (שהוגדר עם extframe=True), אחרת מנקה מזהה סטנדרטי (שהוגדר עם extframe=False).
- recv(fifo: int, list: list | None = None, *, timeout: int = 5000) list¶
מקבל נתונים על האפיק:
fifo הוא מספר שלם, שהוא ה-FIFO שעליו לקבל
list הוא אובייקט רשימה אופציונלי שישמש כערך ההחזרה
timeout הוא הזמן הקצוב במילישניות להמתנה לקבלה.
ערך החזרה: רשימה המכילה חמישה ערכים.
המזהה של ההודעה.
ערך בוליאני המציין אם מזהה ההודעה הוא סטנדרטי או מורחב.
ערך בוליאני המציין אם ההודעה היא הודעת RTR.
ערך ה-FMI (Filter Match Index).
מערך המכיל את הנתונים.
אם list הוא
Noneאז תוקצה רשימה חדשה, וכן אובייקט bytes חדש שיכיל את הנתונים (כאיבר החמישי ברשימה).אם list אינו
Noneאז הוא צריך להיות אובייקט רשימה עם לפחות חמישה איברים. האיבר החמישי צריך להיות אובייקט memoryview שנוצר מ-bytearray או ממערך מסוג »B« או »b«, ולמערך זה חייב להיות מספיק מקום עבור לפחות 8 בתים. אובייקט הרשימה יאוכלס אז עם ארבעת ערכי ההחזרה הראשונים שלעיל, ואובייקט ה-memoryview ישונה בגודלו במקום לגודל הנתונים וימולא באותם נתונים. ניתן לעשות שימוש חוזר באותם אובייקטי רשימה ו-memoryview בקריאות הבאות לשיטה זו, מה שמספק דרך לקבל נתונים מבלי להשתמש ב-heap. לדוגמה:buf = bytearray(8) lst = [0, 0, 0, 0, memoryview(buf)] # No heap memory is allocated in the following call can.recv(0, lst)
- send(data: int | bytes | bytearray, id: int, *, timeout: int = 0, rtr: bool = False, extframe: bool = False, fdf: bool = False, brs: bool = False) None¶
שולח הודעה על האפיק:
data הוא הנתונים לשליחה (מספר שלם לשליחה, או אובייקט חוצץ).
id הוא המזהה של ההודעה שתישלח.
timeout הוא הזמן הקצוב במילישניות להמתנה לשליחה.
rtr הוא ערך בוליאני המציין אם ההודעה תישלח כבקשת שידור מרחוק (remote transmission request). אם rtr הוא True אז רק האורך של data משמש למילוי משבצת ה-DLC של הפריים; הבתים עצמם ב-data אינם בשימוש.
extframe אם True לפריים יהיה מזהה מורחב (29 סיביות), אחרת נעשה שימוש במזהה סטנדרטי (11 סיביות).
fdf עבור בקרי CAN FD, אם מוגדר ל-True, לפריים יהיה פורמט פריים FD, התומך במטעני נתונים של עד 64 בתים.
brs עבור בקרי CAN FD, אם מוגדר ל-True, מצב מיתוג קצב הסיביות מופעל, שבו שלב הנתונים משודר בקצב סיביות שונה. ראה
CAN.init()עבור פרמטרי תצורת תזמון סיבית הנתונים.
אם timeout הוא 0 ההודעה ממוקמת בחוצץ באחד משלושה חוצצי חומרה והשיטה חוזרת מיד. אם כל שלושת החוצצים בשימוש נזרקת חריגה. אם timeout אינו 0, השיטה ממתינה עד שההודעה משודרת. אם לא ניתן לשדר את ההודעה בתוך הזמן שצוין נזרקת חריגה.
ערך החזרה:
None.
- rxcallback(fifo: int, fun: Callable[[CAN, int], None] | None) None¶
רושם פונקציה שתיקרא כאשר הודעה מתקבלת לתוך FIFO ריק:
fifo הוא ה-FIFO הקולט.
fun היא הפונקציה שתיקרא כאשר ה-FIFO הופך ללא-ריק.
פונקציית ה-callback מקבלת שני ארגומנטים: הראשון הוא אובייקט ה-CAN עצמו; השני הוא מספר שלם המציין את הסיבה ל-callback:
סיבה
משמעות
0הודעה התקבלה לתוך FIFO ריק.
1ה-FIFO מלא.
2הודעה אבדה עקב FIFO מלא.
דוגמה לשימוש ב-rxcallback:
def cb0(bus, reason): print('cb0') if reason == 0: print('pending') if reason == 1: print('full') if reason == 2: print('overflow') can = CAN(1, CAN.LOOPBACK) can.rxcallback(0, cb0)
קבועים (Constants)¶
קבועי מצב-אפיק (ארגומנט
modeשלinit()):- LOOPBACK: int¶
מצב loopback פנימי: הבקר מנותק מהפינים ומנתב את הפריימים המשודרים ישירות בחזרה לנתיב הקבלה. שימושי לבדיקות עצמיות ללא transceiver.
- SILENT: int¶
מצב האזנה-בלבד: הבקר מקבל פריימים אך לעולם אינו מניע את האפיק (ללא ACK, ללא שידורים). שימושי לצותת לאפיק (sniffing).
- SILENT_LOOPBACK: int¶
משלב
SILENTו-LOOPBACK: ללא פעילות בפינים וללא אישורים, עם loopback פנימי של TX לתוך RX.
קבועי מצב-בקר (מוחזרים על ידי
state()):מצבי מסנן CAN-קלאסי (ארגומנט
modeשלsetfilter()ב-OpenMV Cam M4 / M7):מצבי מסנן CAN FD (ארגומנט
modeשלsetfilter()ב-OpenMV Cam H7 / H7 Plus / Pure Thermal):