arduino_spi_slave.py

# هذا العمل مرخص بموجب ترخيص MIT.
# حقوق النشر (c) 2013-2023 OpenMV LLC. جميع الحقوق محفوظة.
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# SPI مع Arduino كجهاز رئيسي (master) و OpenMV Cam كجهاز تابع (slave).
#
# يرجى توصيل جهاز OpenMV Cam بجهاز Arduino كما يلي:
#
# OpenMV Cam Master Out Slave In (P0) - Arduino Uno MOSI (11)
# OpenMV Cam Master In Slave Out (P1) - Arduino Uno MISO (12)
# OpenMV Cam Serial Clock (P2) - Arduino Uno SCK (13)
# OpenMV Cam Slave Select (P3) - Arduino Uno SS (10)
# OpenMV Cam Ground - Arduino Ground

import pyb
import struct
import time

text = "Hello World!\n"
data = struct.pack("<bi%ds" % len(text), 85, len(text), text)  # 85 هو محرف المزامنة (sync char).
# استخدم "struct" لبناء حزم البيانات المراد إرسالها.
# "<" يضع البيانات في البنية (struct) بترتيب little endian.
# "b" يضع محرفاً موقّعاً (signed char) في تدفق البيانات.
# "i" يضع عدداً صحيحاً موقّعاً (signed integer) في تدفق البيانات.
# "%ds" يضع نصاً (string) في تدفق البيانات. على سبيل المثال "13s" لـ "Hello World!\n" (13 محرفاً).
# انظر https://docs.python.org/3/library/struct.html

# اقرأني!!!
#
# يرجى العلم أنه عندما لا يكون OpenMV Cam هو جهاز SPI الرئيسي (master)، فقد يفوّت الاستجابة لـ
# إرسال البيانات كجهاز SPI تابع (slave) بغض النظر عمّا إذا كنت تستدعي "spi.send()" داخل دالة استدعاء مقاطعة (interrupt callback) أو في
# الحلقة الرئيسية أدناه. لذلك يجب عليك تصميم بروتوكول الاتصال الخاص بك بحيث
# أنه إذا لم يستدعِ الجهاز التابع (OpenMV Cam) دالة "spi.send()" في الوقت المناسب، فإن البيانات العشوائية (garbage data)
# التي تُقرأ من طرف SPI الطرفي بواسطة الجهاز الرئيسي (Arduino) يتم التخلص منها. ولتحقيق ذلك نستخدم
# محرف مزامنة قيمته 85 (بالثنائي 01010101) الذي سيبحث عنه Arduino كأول بايت يتم قراءته.
# إذا لم يجد هذا المحرف فإنه يُلغي معاملة SPI ويحاول مرة أخرى. ثانياً، ومن أجل
# مسح حالة طرف SPI الطرفي، نرسل دائماً عدداً من البايتات مضاعفاً للأربعة بالإضافة إلى أربعة بايتات صفرية إضافية
# للتأكد من أن طرف SPI الطرفي لا يحتفظ بأي بيانات قديمة يمكن أن تكون قيمتها 85. لاحظ
# أن OpenMV Cam سيفوّت نافذة "spi.send()" بشكل عشوائي لأنه يتوجب عليه خدمة
# المقاطعات (interrupts). ستحدث المقاطعات بشكل أكبر بكثير أثناء الاتصال بجهاز الكمبيوتر الخاص بك.

# ناقل SPI الخاص بالعتاد في كاميرا OpenMV هو دائمًا الناقل رقم 2.
# polarity = 0 -> تكون الساعة (clock) في حالة سكون منخفضة (idle low).
# phase = 0 -> يتم أخذ عينة من البيانات عند الحافة الصاعدة للساعة، وإخراج البيانات عند الحافة الهابطة.
spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0)


# دالة استدعاء NSS (NSS callback).
def nss_callback(line):
    global spi, data
    try:
        spi.send(data, timeout=1000)
    except OSError as err:
        pass  # لا داعي للاهتمام بالأخطاء - لذا استخدم pass.
        # لاحظ أن هناك 3 أخطاء محتملة: خطأ انتهاء المهلة (timeout)، خطأ عام، أو
        # خطأ الانشغال (busy). أكواد الأخطاء هي 116 و5 و16 على التوالي لـ "err.arg[0]".


# قم بضبط NSS/CS في وضع IRQ لإرسال البيانات عند الطلب من الجهاز الرئيسي (master).
pyb.ExtInt(pyb.Pin("P3"), pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, nss_callback)

while True:
    time.sleep_ms(1000)

###################################################################################################
# كود Arduino
###################################################################################################
#
# #include <SPI.h>
# #define SS_PIN 10
# #define BAUD_RATE 19200
# #define CHAR_BUF 128
#
# void setup() {
#   pinMode(SS_PIN, OUTPUT);
#   Serial.begin(BAUD_RATE);
#   SPI.begin();
#   SPI.setBitOrder(MSBFIRST);
#   SPI.setClockDivider(SPI_CLOCK_DIV16);
#   SPI.setDataMode(SPI_MODE0);
# delay(1000); // امنح جهاز OpenMV Cam وقتاً للإقلاع (bootup).
# }
#
# void loop() {
#   int32_t len = 0;
#   char buff[CHAR_BUF] = {0};
#   digitalWrite(SS_PIN, LOW);
# delay(1); // امنح جهاز OpenMV Cam بعض الوقت للاستعداد لإرسال البيانات.
#
# if(SPI.transfer(1) == 85) { // هل تمت رؤية محرف المزامنة؟
# SPI.transfer(&len, 4); // الحصول على الطول
#     if (len) {
#       SPI.transfer(&buff, min(len, CHAR_BUF));
#       len -= min(len, CHAR_BUF);
#     }
# while (len--) SPI.transfer(0); // استهلاك أي بايتات متبقية
#   }
#
#   digitalWrite(SS_PIN, HIGH);
#   Serial.print(buff);
# delay(1); // لا تكرر الحلقة بسرعة زائدة.
# }

results matching ""

    No results matching ""