יום שישי, 1 ביוני 2012

Arduino And .Net


הגיע הזמן שניקח את ה Arduino שלב אחד קדימה, כבר עשינו הכרות , למדנו את הבסיס, ניסינו חיישנים , בדקנו כפתורים ועשינו תעלולים עם Leds, אבל זה לא מספיק, צריך לתקשר עם מערכות חיצוניות, נניח שה Arduino שלנו מלא בחיישנים ואנחנו רוצים להעביר את הנתונים שלהם למחשב אחר או לשמור אותם במסד נתונים.


אז מה עושים?
קיימות מספר דרכים לתקשר עם ה Arduino , הצורה הבסיסית מגיעה עם ה Arduino ולא מצריכה חומרה מיוחדת, בעזרת החיבור הסיראלי הפנימי בלוח ניתן להעביר הודעות מהמחשב האישי ל Arduino וההפך, שיטה אחרת היא ברכישת Shield יעודי עבור התקשורת , ניתן למצוא Shields מגוונים למגוון תקשורות - Wifi, Bluetooth, Ethernet וכו'.

קצת על התוכנית:
המחשב האישי יעביר ל Arduino את ניצול המעבד והזיכרון של מערכת ההפעלה  וה Arduino יציג את המידע ע"ג צג חיצוני.

דרישות:

  • Arduino Uno
  • Arduino LCD Shield
  • USB Cable




Arduino LCD Shield

הלוח מגיע עם 6 כפתורים , ומסך LCD עם תאורה ירוקה בגודל 2 שורות של 16 תווים (ממש פסגת התכנולוגיה) שעולה בסביבות ה 80 ש"ח אבל אפשר למצוא מסכים גדולים יותר, צבעוניים ועם יכולת מגע, למסך עצמו יש חיבור של 16 פינים שתופס את הכניסות הדיגיטליות של ה Arduino, מה שעושה קצת בעייה אם נרצה לחבר רכיבים נוספים , בהמשך לסידרת המאמרים אעבור על איך להגדיל את כמות ה IOs ב Arduino בעזרת 74HC595N Shift Register.



הצד של ה .NET - השולח

התוכנית מובססת על "מרחב שמות" System.IO.Ports שמאפשר לנו להתחבר סיראלית  ל Arduino ולדבר איתו בנוסף קיים שעון שדוגם את המערכת כל שנייה , בעזרת  "מרחב השמות" System.Diagnostics אפשר לדגום רכיבים במערכת Windows ולשלוח אותם ל Arduino, במקרה שלנו הניטור מתבצע על ניצול המעבד והזיכרון הפנוי במחשב בעזרת המחלקה Performance Counter שמנטרת את משאבי המערכת.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO.Ports;

namespace arduino_csharp1
{
    public partial class Form1 : Form
    {
        SerialPort myserial;
        PerformanceCounter cpuCounter;
        PerformanceCounter ramCounter;
        
        
        public Form1()
        {
            InitializeComponent();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (myserial != null)
            {
                if (myserial.IsOpen)
                    myserial.WriteLine(getSysCpu());

            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //create new serial port  
            myserial = new SerialPort();
            //choose baud rate ,default:9600
            myserial.BaudRate = 9600;
            //COM port name you can get it
            //in the Device Manager of windows
            myserial.PortName = "COM6";

            //register to  DataReceived and error events
            //for getting feedback from the Arduino 
            myserial.DataReceived += new SerialDataReceivedEventHandler(myserial_DataReceived);
            myserial.ErrorReceived += new SerialErrorReceivedEventHandler(myserial_ErrorReceived);

            myserial.Open();
        }

        void myserial_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            MessageBox.Show("Error:" + e.ToString());
        }

        void myserial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //get feedback message from the Arduino
            SerialPort s = (SerialPort)sender;
            //lst_box.Items.Add(s.ReadLine());
        }


        private string getSysCpu()
        {
            //getting total CPU usage
            cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
            //getting free memory 
            ramCounter = new PerformanceCounter("Memory", "Available MBytes");

            //capture cpu value need to be compare
            //to previous value that why it's need
            //to be done twice
            float cpuval = cpuCounter.NextValue();
            System.Threading.Thread.Sleep(100);
            cpuval = cpuCounter.NextValue();
            System.Threading.Thread.Sleep(100);

            //capture free memory value
            float memval = ramCounter.NextValue();

            //return string with a symbol # for arduino
            //to split the message between the lines of the screen
            return "CPU:" + Math.Round(cpuval, 0).ToString() + "%#MEM:" + memval.ToString() + "MB";

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            { myserial.Close();}
            catch (Exception ex) { }
        }
    }
}


הצד של Arduino  - המקבל

התפקיד של Arduino הוא להאזין לחיבור הסיראלי  בדומה למה שעשינו ב .Net ,צריכים לאסוף אות אות ולהכניס אותן לתוך Buffer ואח"כ לפרק אותו ל 2 Buffers שונים שכל אחד מהם יחזיק חלק מההודעה לכל שורה (כבר אמרתי שבמסך שלי יש 2 שורות בלבד?), בעזרת סימון מיוחד '#' אנחנו מפצלים את השורות.

שימו לב: ב Arduino קיימת מחלקה מובנת ( LiquidCrystal) לטיפול במסכי LCD שמחליפה מחלקה מיושנת יותר שנקראת LCD4Bit, צריך לאתחל את המסך בסדר פינים שונה מ Shield ל Shield לכן כדאי להכיר את ה  Shield Datasheet שלכם.

#include <LiquidCrystal.h>

//set the LCD pins ,can be different between shields
LiquidCrystal lcd(7, 6, 2,3,4,5);

//global message size
const char MAXIMUM_INPUT_LENGTH = 18;
//global input
char input[MAXIMUM_INPUT_LENGTH + 1] = {'\0'};

//divided buffer 0
char temin[MAXIMUM_INPUT_LENGTH + 1] = {'\0'};
//divided buffer 1
char temin1[MAXIMUM_INPUT_LENGTH + 1] = {'\0'};
//save the position when split happen
char splitChar = -1;
//the currentIndex of the global message
char currentIndex = 0;



void setup()
{
  //set the serial and LCD
  Serial.begin(9600); 
   lcd.begin(16,2);
}

void loop()
{
   if(Serial.available())
   {
      if (currentIndex>=MAXIMUM_INPUT_LENGTH ){
       //start to break the global buffer to 2 buffer split by #   
       for (char i =0 ; i < MAXIMUM_INPUT_LENGTH; i++)
       {
          if(splitChar == -1 && input[i] != '#' )
             temin[i] = input[i];
         else  if(input[i] =='#') 
            splitChar = i;
           else if(splitChar != -1)
             temin1[i- splitChar -1] = input[i];
       }
       
       lcd.clear();
       
       //set the LCD first raw and load the buffer
       lcd.setCursor(0,0); 
       lcd.print(temin);
       //set the LCD second raw and load the buffer
       lcd.setCursor(0,1); 
       lcd.print(temin1);
       
       //check if the message transfer currently
       //back to .net client
       Serial.println(temin); 
       Serial.println(temin1); 
       Serial.flush();
        
        //we need some delay
        delay(100);
        
        //reset the buffer and global values
        clearBuffer();
        splitChar = -1;
        currentIndex = 0;
         
     }
     else
     {
       //while buffer not full, keep set
       //chars in the global input buffer
       input[currentIndex++] = Serial.read(); 
     }
   }
}

void clearBuffer()
{
   for (char i=0; i<=MAXIMUM_INPUT_LENGTH; i++){
         input[i] = '\0';
         temin[i] = '\0';
         temin1[i] = '\0';
    }
}

סיכום:
העבודה עם Shield ומחשב חיצוני הופכת את ה Arduino לכלי רציני לפיתוח ועכשיו הוא פתוח לעולם, בהמשך נעבור על תקשורות נוספות.

שבץ אותו.






אין תגובות:

הוסף רשומת תגובה