تنفيذ نظام التشغيل الآلي للمنزل

لفترة طويلة قرأت مقالات عن حبري حول أنظمة التشغيل الآلي للمنزل ، أردت أن أصف ما كنت أعمل عليه منذ أكثر من عامين. لفهم وضعي بشكل أفضل ، تحتاج إلى تقديم مقدمة صغيرة.

منذ ثلاث سنوات ، انتقلت أنا وعائلتي إلى شقة جديدة من ثلاث غرف (67.5 مترًا مربعًا) ، على الرغم من أن الشقة من الناحية الفنية قديمة بالطبع - مبنى ستالين ، بني عام 1946. أسلاك ألمنيوم بسلكين بقطع نحاسية مجدولة كبل 1 متر مربع في بعض الأماكن. كان الإصلاح شاملاً ، قررت أن أفعل كل شيء بنفسي ، وبدأت باستبدال كامل للأسلاك. تم شراء 700 متر من كابل الطاقة للإضاءة والمآخذ 1.5 و 2.5 متر مربع ، خليج مزدوج مجدول ، محوري صغير لهوائيات التلفزيون (فقط في حالة). لماذا الكثير وما جاء منه - أطلب قطة.

قررت أن أجعل الأسلاك على الفور ، وهي: بدون صناديق التوزيع ، من كل نقطة يذهب الكبل إلى الدرع (باستثناء المنافذ ، التي يمكن أن تكون في مجموعة من 2-3 نقاط ، الكبل يذهب إلى الدرع من أقصى ، والباقي متصل بحلقة) - ر. ه. من كل تبديل الكابل الخاص به إلى الدرع ، من كل نقطة إضاءة كابله الخاص إلى الدرع ، بالقرب من المقابس على طول زوج من نقاط rj-45 ، في حالة حدوث ذلك. بالطبع ، هناك العديد من الكابلات. في مكان ما ، يتم وضعه في الأرضية وفقًا لجميع قواعد PUE ، كما هو الحال ، على سبيل المثال ، في الحضانة: في



مكان ما - على السقف ، على سبيل المثال ، منظر باب غرفة النوم:



ونتيجة لذلك ، نحصل على جميع الكابلات في الممر في مكان واحد حيث سيتم وضع الدرع ، ويمكن تبديلها فيما بينها كما تريد. حتى إذا اضطررت إلى تغيير نظام الاتصال في المستقبل ، فلن يستغرق الأمر وقتًا طويلاً ولن تضطر إلى إفساد الإصلاح. وبالطبع ، تم عمل العديد من المقابس لجميع المناسبات - في المجموع حوالي 90 نقطة للشقة بأكملها.

هذا ما بدا عليه "الدرع" المؤقت خلال التجارب:



مشهد رهيب ، لكن كل شيء نجح وبهذا الشكل عاش هذا الوحش لعدة أشهر. في أحد الأيام الجميلة ، تم تشكيل النجوم بنجاح وتم إعادة تصميم الدرع بقرار متعمد. استغرق الأمر 3 أيام على سلم متدهور تحت السقف (والسقوف في ستالين 3 م) ، لكن الأمر كان يستحق ذلك. وإليك كيف بدأ الحاجب في الظهور بعد ذلك:



والرأي العام:



هذا بعيد عن الشكل النهائي للدرع ، ولا يزال هناك ما يكفي من التجمع الكونغولي من أجل الديمقراطية ، وهناك 3 مرات أقل من قواطع الدائرة عما هو ضروري ، ولا توجد مرحلات نبضية - ولكن هناك خطوط غير متصلة ، وجميع الكابلات متصلة بالمطاريف ، وهناك على الأقل نوع من انتقائية قاطع الدائرة.

الآن بعد أن أصبحت لديك فكرة تقريبية عما كان علي العمل به بالضبط ، يمكنك البدء في وصف "أدمغة" النظام. بدون مزيد من اللغط ، أخذت arduino كأساس ، خاصة وأنني قد حصلت بالفعل على لوحين freeduino ، ودرعتين ethernet ودرع محرك اشتريته قبل ذلك بوقت طويل. كما تم طلبها من الصينيين عدة وحدات ترحيل كل منها 4 قطع. ووجدت أيضًا ، بناءً على نصيحة إحدى المقالات حول حبري في أوب ، مفاتيح يمكن فيها إدخال زنبركات خاصة وتحويلها إلى مفاتيح دون إصلاح. حان الوقت لكتابة التعليمات البرمجية.

بشكل عام ، أنا على اتصال وثيق بأجهزة الكمبيوتر في الحياة. أنهى حصيرة الفرو ، التي لم يكتب عليها - باسكال ، سي # ، سي ++ ، 1 سي ، فب ، جافا سكريبت - لا يزال بإمكانك سرد الكثير. في المرة الأخيرة التي أعمل فيها في مجال تطوير الويب ، أتعامل أيضًا مع IP-telephony. لذلك ، يعد التوصل إلى خوارزمية أمرًا بسيطًا ، ولكن مع الإلكترونيات "من أجلك" ، أعرف وأعلم أشياء بسيطة ، وعندما يتعلق الأمر بشيء أكثر تعقيدًا - وحدات التحكم الدقيقة ، الصمامات ، ارتداد الاتصال - يكون الأمر أكثر صعوبة. لكن ليس الآلهة هم الذين يحرقون الأواني ، والعين خائفة ، ولكن اليدين تفعل ذلك. قررت أن أبسط كل شيء. أقوم بتغذية الأرض من arduino إلى إدخال المفتاح ، أقوم بتوصيل المخرجات من التبديل إلى دبابيس تناظرية على arduino (على الرغم من أنه من الممكن إلى رقمي ، فإنه ليس مهمًا). أقوم بتوصيل دبابيس اردوينو بالدبابيس على وحدة التتابع. من الناحية الفنية ، كل شيء جاهز ، عندما تضغط على المفتاح ، يرى arduino القيمة LOW على الدبوس المطلوب ويضبط LOW على الدبوس المتصل بوحدة التتابع.بالنظر إلى أن جميع الكابلات من النقاط في الشقة تأتي إلى المحطات الطرفية - لم يستغرق الاتصال الكثير من الوقت.
لمكافحة ارتداد جهات الاتصال ، بعد دراسة الموضوع على الإنترنت ، تم اختيار مكتبة Bounce2. بشكل عام ، أردت في البداية كتابة رمز عالمي بحيث يمكن استخدامه مع مفتاحين على الأقل ، على الأقل 22. وكانت هذه المهمة هي التي شكلت أساس الخوارزمية بأكملها. حسنًا ، الآن من الكلمات إلى التعليمات البرمجية. لن أقوم بتحميل جميع التعليمات البرمجية بالكامل ؛ ستكون الروابط إلى github في نهاية المقالة. سوف أظهر لحظات مهمة فقط ، من وجهة نظري.

إذن ، التصريح عن المكتبات والمتغيرات:

#include <Bounce2.h>
#include <EEPROM.h>

const byte cnt = 8;
const byte pin_cnt = 19;

int pins[] = {11,12,13,13,14,15,16,17};
int leds[] = {6, 3, 4, 5, 3, 4, 5, 3};

byte init_leds[cnt] ;
byte init_buttons[cnt];
int button_states[cnt];
Bounce debouncers[cnt];
unsigned long buttonPressTimeStamps[cnt];
boolean changed[cnt];

النقطة هي: يكفي زيادة الثابت مع عدد المصابيح / المفاتيح وتسجيل اقترانات جديدة في المصفوفات - وهذا كل شيء ، سيتم إضافة مصباح أو مفتاح جديد. في نفس الوقت ، تسمح بنية الكود لمفتاح واحد بالتحكم في العديد من التركيبات في وقت واحد. أو عدة مفاتيح للتحكم في مصباح واحد على الفور. أيضًا ، لكل مفتاح تبديل ، يتم إنشاء مثيله الخاص بكائن Bounce لمقاومة الارتداد.

في وظيفة الإعداد ، تتم تهيئة جميع المصفوفات ، بينما يتم تخزين حالة المصابيح في ذاكرة غير متقلبة ، بحيث عندما يحدث انقطاع التيار أو إعادة التشغيل ، يتم تشغيل كل شيء بنفس الطريقة التي كانت عليها قبل الفشل.

  for(byte i=0; i<cnt; i=i+1) {
    EEPROM.write(pins[i], 10);
  }

  for(byte i=0; i<cnt; i=i+1) {
    button_states[i] = 0;
    
    byte value = EEPROM.read(leds[i]);
    if(value==11) {
      init_leds[i] = LOW ;
    }else{
      init_leds[i] = HIGH ;
    }
    init_buttons[i] = HIGH;
    buttonPressTimeStamps[i] = 0;
    changed[i] = false;

    debouncers[i] = Bounce();

    pinMode(pins[i], INPUT);
    pinMode(leds[i], OUTPUT);
    
    digitalWrite(pins[i], init_buttons[i]);
    digitalWrite(leds[i], init_leds[i]);
    
    debouncers[i].attach( pins[i] );
    debouncers[i].interval(5);
  }

لن أقول أي شيء عن الدورة الأولى ، وسوف نعود إليها بعد ذلك بقليل. والأكثر إثارة للاهتمام يبدأ في جسم الدورة الرئيسية.

void loop(){
  for(byte i=0; i<cnt; i=i+1){
    byte dvalue = EEPROM.read(pins[i]);
    if(dvalue!=11) {
      changed[i] = debouncers[i].update();
      
      if ( changed[i] ) {
        int value = debouncers[i].read();
        if ( value == HIGH) {
         button_states[i] = 0;   
        } else {
           if (i > 0 and pins[i] == pins[i-1]) {
             byte prev_value = EEPROM.read(leds[i-1]);
                            
             if(prev_value == 11) {
               digitalWrite(leds[i], LOW );
               EEPROM.write(leds[i], 11);
             }else{
               digitalWrite(leds[i], HIGH);
               EEPROM.write(leds[i], 10);
             }
           } else {               
             byte value = EEPROM.read(leds[i]);
             if(value==11) {
               digitalWrite(leds[i], HIGH );
               EEPROM.write(leds[i], 10);
             }else{
               digitalWrite(leds[i], LOW);
               EEPROM.write(leds[i], 11);
             }
           }
                 
           button_states[i] = 1;
           buttonPressTimeStamps[i] = millis();     
        }
      }
   
      if ( button_states[i] == 1 ) {
        if ( millis() - buttonPressTimeStamps[i] >= 200 ) {
            button_states[i] = 2;
        }
      }
    }
  }

  delay( 10 );
} 

خلال اختبارات الإصدارات الأولى من الخوارزمية ، لوحظ أن الأطفال (ولدي ثلاثة منهم ، صبيان) أحبوا حقًا النقر فوق المفاتيح. لذلك ، كان من الضروري أن تكون قادرًا على إيقاف تشغيل بعض المفاتيح حتى لا تستجيب وحدة التحكم لها. الخيار الأكثر وضوحًا هو ببساطة إزالة الدبابيس الضرورية من اللوحة ، ولكن هذا خطأ وغير مثير للاهتمام. لذلك ، يتم أيضًا كتابة الأعلام إلى الذاكرة غير المتطايرة مما يشير إلى ما إذا كان المفتاح مفتوحًا أم لا. تتم تهيئة هذا مع هذه الحلقة:

  for(byte i=0; i<cnt; i=i+1) {
    EEPROM.write(pins[i], 10);
  }

  ...

ودققت هنا:

  for(byte i=0; i<cnt; i=i+1){
    byte dvalue = EEPROM.read(pins[i]);
    if(dvalue!=11) {
    ...

بالفعل في هذه المرحلة ، بدأت المفاتيح المحلية على الجدران تعمل. لكن المنزل الذكي لن يكون ذكيًا بدون واجهة. نظرًا لأنني أتعامل مع تطوير الويب ، فقد تقرر إنشاء واجهة ويب. هذا هو المكان الذي جاءت فيه دروع إيثرنت في متناول اليدين. للأسف ، لم أتمكن من العثور على مصادر الإصدارات الأولى من البرامج التي تستخدم دروع إيثرنت للتحكم عن بعد. سأحاول البحث في النسخ الاحتياطية ، ربما تكون هناك. لكن المعنى كان بدائيًا للعار. كل وحدة تحكم لها عنوان IP الخاص بها. كان خادم الويب يرتفع على أردوينو ، والذي حلل طلبات GET وتشغيل المصباح المقابل أو إيقافه اعتمادًا على رقم المنفذ. هناك الكثير من الأمثلة من هذا النوع على الإنترنت. لواجهة الويب ، تم إنشاء خادم على اللوحة الأم مع Intel Atom ، تم تثبيت Ubuntu Server 14.02 ، تم تثبيت مجموعة LAMP القياسية ،تتم كتابة واجهة بسيطة هناك. ستكون جميع المصادر أيضًا في نهاية المقالة. في الوقت الحالي ، يبدو مثل هذا:



كما ترى ، يتم تشغيل مصباح واحد في المطبخ ، والمفتاح المسؤول عنه مغلق. الإدارة بسيطة للغاية - ما عليك سوى النقر على العنصر المطلوب وتغيير حالته.

وكل شيء سيكون رائعًا ، إن لم يكن لـ "لكن" واحد. علقت دروع إيثرنت باستمرار. لا ، كان التحكم المحلي من المفاتيح يعمل دائمًا مثل الساعة. لكن جهاز التحكم عن بعد من واجهة الويب سقط باستمرار. إذا عملت الإدارة ليوم واحد ، كانت ممتازة. ولكن في كثير من الأحيان ، تم تعليق الدرع بعد ساعات قليلة من إعادة التشغيل. ما لم أفعله للتو هو محاولة التعامل مع كلب الحراسة ، لكن لوحاتي لم تدعمه. لقد طلبت في الصين واستبدلت الدروع بأخرى - على en28j60 - تحسنت ، لكنها لا تزال معلقة بشكل دوري. أضفت وحدة ترحيل إلى وحدة التحكم ، وجلبت الطاقة إلى لوحات arduino من خلال جهات الاتصال المغلقة عادة عليها ، وسحبت إحدى لوحات arduino التتابع بتردد معين وتم قطع الطاقة ، ثم تم استعادتها - ومع ذلك ، لم يكن هذا يعمل دائمًا ، وكان يومض في وقت إعادة التشغيل الضوء يعمل،حتى لبضع ثوان ، ولكن مع ذلك. إليك ما تبدو عليه وحدة التحكم في هذه المرحلة:



ثم تقرر التخلي تمامًا عن دروع إيثرنت. لقد بدأت في البحث عن ميزات الإدارة عن بعد الأخرى. حاولت توصيل اردوينس مباشرة بالخادم وأرسل أوامر عبر Serial.read () / Serial.print () - لقد عملت في كل مرة ، ولم يتحقق الاستقرار لأن اللوحة تتم إعادة تشغيلها في كل مرة يتم الوصول إليها من برنامج نصي على الخادم. لقد قرأت الكثير عن مثل هذه الأخطاء ، أدركت للتو أنها كانت مرتبطة بـ DTR ، في مكان ما كتبوا أنه يمكنك تهيئة المنفذ بعلامات أخرى ، وقدموا أمثلة لم تنجح معي. بعد فترة ، صادفت مقالة حول إنشاء محول USB-I2C من مبرمج USBAsp. قررت - لماذا لا؟ طلبت زوجين من هؤلاء المبرمجين من الصينيين وانتظرت.

وقبل أسبوع وصلت شحنتي. تم وميض أحد المبرمجين مع برنامج i2c الصغير USB الثابت وجلست مرة أخرى لإعادة كتابة التعليمات البرمجية. هنا بدأت ميزات البروتوكول بالظهور. بالطبع ، كان الخادم هو السيد ، وكانت جميع لوحات Arduino عبيدًا.

يجب أن يحل الرمز المهام التالية:

- الإبلاغ عن حالة المنفذ المطلوب ؛
- تبديل حالة المنفذ المطلوب ؛
- إطفاء أو تشغيل جميع الأضواء.

وواجهت مشكلة. يمكنني استخدام الأوامر القياسية من مجموعة أدوات i2c للتواصل مع لوحات arduino. هذا فريق

i2cget -y < > <>

و

i2cset -y < > <> 0x00 <byte >

يبدو أنه ، إذا حكمنا من قبل الرجال ، يمكنك تمرير قيمة الكلمة ، لكنها لم تنجح معي ، أو كنت مخطئًا في مكان ما.

تكمن المشكلة في ، أولاً ، إذا كنت بحاجة إلى تبديل حالة منفذ معين ، فيجب أولاً تمرير رقم الأمر المسؤول عن هذه العملية ، ثم رقم المنفذ. حتى أنني حاولت القيام بذلك ، وأرسل أمرين ، وفي الكود لأجمعهما في المقابل - لكن ذلك كان قبيحًا وغير منطقي.

المشكلة الثانية - لا تستطيع أردوينو الإجابة على شيء في الوقت الذي تتلقى فيه البيانات. هناك طريقتان في مكتبة Wire - onReceive () عند تلقي البيانات من الرئيسي و onRequest () عندما تطلب البيانات من قبل الرئيسي.

لذلك فعلت هذا: يحتوي خادم الويب على 6 أوامر:

  • الأمر "1" - الحصول على حالة جميع الأضواء
  • الأمر "2" - الحصول على حالة الحظر لجميع مفاتيح التبديل
  • الأمر "5" - تشغيل العالم كله
  • الأمر "6" - إيقاف العالم كله

تم تشكيل أمر على النحو التالي: رقم عشري من النموذج التالي <مئات (1 أو 2) - قم بتبديل المصباح أو مفتاح القفل> <رقم المنفذ (من 0 إلى 99)> ؛ على سبيل المثال ، 105 - مفتاح 5 منافذ ، 213 - مفتاح قفل 13 منفذًا. يتم ترجمة هذا الأمر إلى سداسي عشري ويتم تمريره إلى الأردوينو ، الذي يقوم بالتحويلات العكسية ويفهم ما يجب القيام به.

إليك ما يبدو عليه من جانب الخادم:

  ...
  if ($action == 3)
     $val_hex = dechex(intval($port) + 100);
  else
     $val_hex = dechex(intval($port) + 200);
  
  exec("sudo i2cset -y 7 $addr 0x00 0x$val_hex", $output);
  ...

ومن جانب اردوينو:

void receiveEvent(int howMany) {
  byte bytes = Wire.available();
  int x = 0;
  for (byte i=1; i <= bytes; i=i+1) {
    x = Wire.read();
  }
  
  if (x == 1 or x == 2 or x == 5 or x == 6) {
    do_action(x, 0);
  } else {
    if ( x > 200) {
      do_action (4, x - 200);
    } else {
      do_action (3, x - 100);
    }
  }  
}

يبدو بدائيًا تمامًا ، لكنه يعمل. يتم حل المشكلة الثانية على النحو التالي. هنا وظيفة do_action:

void do_action(byte command, byte port) {
  byte value = 0;
  byte dvalue = 0;
  switch (command) {
    case 1:
      start_request = true;
      request_type = 1;
      current_port = 0;
      
      break;
    case 2:
      start_request = true;
      request_type = 2;
      current_port = 0;
      
      break;
    case 3:
      value = EEPROM.read(port);
      if(value==11) {
        digitalWrite(port, HIGH);
        EEPROM.write(port, 10);
      } else {
        digitalWrite(port, LOW);
        EEPROM.write(port, 11);
      }
      
      break;
    case 4:
      dvalue = EEPROM.read(port);
      if(dvalue==11) {
        EEPROM.write(port, 10);
      } else {
        EEPROM.write(port, 11);
      }
      
      break;
    case 5:
      for (byte i=0; i<cnt; i = i + 1) {
        digitalWrite(leds[i], LOW);
        EEPROM.write(leds[i], 11);
      }
      
      break;
    case 6:
      for (byte i=0; i<cnt; i = i + 1) {
        digitalWrite(leds[i], HIGH);
        EEPROM.write(leds[i], 10);
      }
      
      break;
    default:
      
    break;
  }
}

مع الفرق 3-6 ، كل شيء واضح ، ولكن يمكن وصف الفرق 1 أو 2 بمزيد من التفصيل. يرسل الخادم الأمر المطلوب أولاً ، وعندما يتلقى arduino الأمر 1 أو 2 ، تتم تهيئة العلامات:

  start_request = true;
  request_type = 1;
  current_port = 0;

ثم يبدأ الخادم في إرسال الطلبات إلى أردوينو عدة مرات مثل المنافذ التي يريد الاقتراع. على جانب الخادم:

function get_data($address, $action, $cnt) {
	exec("sudo i2cset -y 7 $address 0x00 0x0$action", $output);
	$tmp = @$output[0];
	while (strpos($tmp,"rror")!==false) {
		exec("sudo i2cset -y 7 $address 0x00 0x0$action", $output);
		$tmp = @$output[0];
	}
	$str = "";
	for ($i = 1; $i <= $cnt; $i++) {
		exec("sudo i2cget -y 7 $address", $output);
		$tmp = @$output[0];
		while (strpos($tmp,"rror")!==false) {
			exec("sudo i2cget -y 7 $address", $output);
			$tmp = @$output[0];
		}
		if ($tmp) {
			if (strpos($tmp,"1")!==false)
				$str .= "1";
			else
				$str .= "0";
		}
		unset($output);
		unset($tmp);
	}
			
	return $str;
}

$str = array();
$c = 1;
while ($c <= $tryes) {
	$tmp = get_data($addr, $action, $cnt);
	
	if (strlen($tmp) == $cnt)
		$str[] = $tmp;
	
	$c++;
}

$new_array = array_count_values($str);

asort($new_array);

$res = "";
$max = 0;
foreach ($new_array AS $key=>$val) {
	if ($val >= $max) {
		$res = $key;
		$max = $val;
	}
}

return preg_split('//', $res, -1, PREG_SPLIT_NO_EMPTY);

باختصار - نحن نجري عدة محاولات ($ tryes> 3) لاستجواب اردوينو ، نحصل على خط يتكون من 0 أو 1. في كل مكان مع أي أمر ننظر إلى الإجابة ، إذا كان هناك كلمة خطأ - فهذا يعني وجود أخطاء أثناء النقل وتحتاج إلى تكرار النقل . تم إجراء العديد من المحاولات لضمان صحة السلسلة المرسلة ، يتم طي المصفوفة بسلسلة باستخدام طريقة array_count_values ​​($ str) ؛ وفي النهاية نحصل على مصفوفة تحتوي على عدد مرات حدوث نفس السطور ، ونعطي الخط الذي تلقيناه أكثر من كل شيء من اردوينو.

من جانب اردوينو كل شيء أبسط:

void requestEvent() {
  if (request_type == 1) {
    byte value = EEPROM.read(leds[current_port]);
    if(value==11) {
      Wire.write(1);
    } else {
      Wire.write(0);
    }
    
    current_port = current_port + 1;
  } else if (request_type == 2) {
    byte dvalue = EEPROM.read(pins[current_port]);
    if(dvalue==11) {
      Wire.write(1);
    } else {
      Wire.write(0);
    }

    current_port = current_port + 1;
  }
}

يحتوي رمز صفحة الويب على عناصر التحكم:

<a class="lamp living_room" id="lamp0x4d3" rel='0x4d' onclick="lamp_click('0x4d',this.id, 3);" ></a>
<a class="lamp kitchen" id="lamp0x4d4" rel='0x4d' onclick="lamp_click('0x4d',this.id, 4);" ></a>
<a class="lamp children_main" id="lamp0x4d5" rel='0x4d' onclick="lamp_click('0x4d',this.id, 5);" ></a>
<a class="lamp children_second" id="lamp0x4d6" rel='0x4d' onclick="lamp_click('0x4d',this.id, 6);" ></a>
<a class="lamp sleeproom_main" id="lamp0x423" rel='0x42' onclick="lamp_click('0x42',this.id, 3);" ></a>
<a class="lamp sleeproom_lyuda" id="lamp0x424" rel='0x42' onclick="lamp_click('0x42',this.id, 4);" ></a>
<a class="lamp sleeproom_anton" id="lamp0x425" rel='0x42' onclick="lamp_click('0x42',this.id, 5);" ></a>

<a class="button button_living_room" id="button0x4d15" onclick="button_click('0x4d',this.id, 15);" ></a>
<a class="button button_kitchen" id="button0x4d14" onclick="button_click('0x4d',this.id, 14);" ></a>
<a class="button button_children_main" id="button0x4d16" onclick="button_click('0x4d',this.id, 16);" ></a>
<a class="button button_children_second" id="button0x4d17" onclick="button_click('0x4d',this.id, 17);" ></a>
<a class="button button_sleeproom_door1" id="button0x4212" onclick="button_click('0x42',this.id, 12);" ></a>
<a class="button button_sleeproom_door2" id="button0x4213" onclick="button_click('0x42',this.id, 13);" ></a>
<a class="button button_sleeproom_lyuda1" id="button0x4214" onclick="button_click('0x42',this.id, 14);" ></a>
<a class="button button_sleeproom_lyuda2" id="button0x4215" onclick="button_click('0x42',this.id, 15);" ></a>
<a class="button button_sleeproom_anton1" id="button0x4216" onclick="button_click('0x42',this.id, 16);" ></a>
<a class="button button_sleeproom_anton2" id="button0x4217" onclick="button_click('0x42',this.id, 17);" ></a>

في الواقع ، أنا أشير بشكل صريح إلى عنوان اللوحة الذي أحتاج إلى الوصول إليه ورقم المنفذ.

أوه نعم ، تبدو وحدة التحكم كما يلي الآن:



بعد تثبيت كل شيء في مكانه ، بدأ كل شيء في المرة الأولى. وفي اليوم التالي ، ظهر تأثير غير مفهوم - إذا قمت بتشغيل جميع الأضواء في غرفة النوم ، يبدأ كل ضوء غرفة النوم في الوميض كل 2-3 ثوانٍ. قضيت الليل كله في اختيار الرمز ؛ لم يكن هناك مثل هذا العضادة على منصة الاختبار ، لذا فإن المشكلة ليست في الرمز. قمت بتفتيش مجموعة من المنتديات ، في توغا واحدة منها وجدت وصفا لأعراض مماثلة ، وتحققت من تخميني - واختفت المشكلة. وكانت النقطة كلها هي أنني أطعمت جميع arduins الثلاثة من مصدر طاقة الكمبيوتر ، 12V ، وأكل freeduino القديم بهدوء ولم يسمع ، ولم يستطع arduino uno v3 ، وعندما تم تشغيل جميع المرحلات ، تم تسخين منظم الطاقة بحيث كان من المستحيل لمسها. خفض جهد الإمداد إلى 5V 2A - وعملت كما يجب.

هناك الكثير من الخطط ، نحتاج إلى إنهاء الإصلاح في الشقة ، الممر والحمام مع المرحاض في الطابور ، في أحلامي أريد التحكم في سخان الماء وكل منفذ ، حيث يمكنني الآن تعليق أي كمية من الأردوين على حافلة I2C وكل منها سوف يقوم بأمره الخاص. ومن المقرر أيضًا إضافة مرحلات النبض إلى سكة din بحيث تتحكم وحدات الترحيل في مرحلات النبض هذه فقط ، ويمر الحمل بأكمله عبر الأخير. لأن هناك شكوك جدية حول موثوقية وحدات التتابع الصينية. ولكن هذا كل شيء في المستقبل.

كما وعد ، روابط إلى github:

واجهة ويب Sketchy
لـ Arduino

Source: https://habr.com/ru/post/ar386457/


All Articles