‏הצגת רשומות עם תוויות communication. הצג את כל הרשומות
‏הצגת רשומות עם תוויות communication. הצג את כל הרשומות

יום שבת, 23 באוגוסט 2014

Arduino Yun - Starting Guide




עד עכשיו ראינו 2 סוגים של לוחות פיתוח, הראשון היה Arduino שמבוסס על מעבד פשוט ללא מערכת הפעלה, לעומתו ראינו את BeagleBone ואת Raspberry PI שמבוססים על מעבדים יותר מתוחכמים שמריצים Linux, מפתחי Arduino לא יכלו להיות אדישים והוציאו דגם חדש שמשלב בתוכו את 2 העולמות.

הוא מכיל 2 מעבדים, הראשון והמוכר ATmega 328u4 במהירות 16MHZ ו 32KB של זיכרון ,הוא אחראי על העבודה מול החיבורים הדיגטליים והאנלוגים המקוריים שיש בגרסת ה Uno הותיקה, המעבד השני הוא Atheros AR 9331 שמבוסס על ארכיטקטורת MIPS במהירות 400Mhz עם 64MB של זיכרון, הוא אחראי על שאר ה Peripherals כמו הרשת הקווית ,האלחוטית ,כרטיס הזיכרון וה USB ,הלוח מריץ מערכת OpenWRT שכתבתי עליה בעבר.

דרישות

  • Arduino Yun
  • Led
  • 330ohm Resistor
  • Wires

בגודל של Uno

הפעלה ראשונית

הלוח מגיע מוכן, מה שנשאר לעשות הוא לחבר אליו חשמל ולהתחבר ל Access Point שהוא יוצר אוטומטית, נפתח את הדפדפן ונכניס את הכתובת של ה Default Gateway שקיבלנו (במקרה שלי 192.168.201.223), דרכה נגיע לממשק הניהול.


הסיסמא ההתחלתית היא arduino

הממשק עצמו מאוד פשוט, דרכו ניתן להגדיר את התקשורת WIFI, אבל יש בו אפשרות נוספת שכדאי להכיר שנקראת Rest API , זה המנגנון דרכו נדבר עם המעבד ATmega דרך שרת Http ששולט על הפינים כפי שנראה בהמשך.

חלק קטן מ OpenWRT


הממשק הבסיסי מאוד פשוט ועונה על הצרכים למתחילים, אבל למי שרוצה להעמיק ניתן להתחבר לממשק המקורי של OpenWRT שמזכיר מאוד נתב סטנדרטי על ידי לחיצה על הקישור Advanced Configure Panel.

טירוף...


Bridge

לפני שנתחיל לכתוב את התוכנית המגשרת בין 2 המעבדים, תחילה יש להשתמש בסביבת Arduino מעודכנת מעל 1.5 שמכילה את הספריות של Yun ו Driver חדש יותר שתומך בלוח,את התוכנית צורבים על הזיכרון של המעבד ATmega בצורה סטנדרטית כמו שעושים לשאר הלוחות של Arduino, רק חשוב לבחור את הלוח המתאים ברשימה, קיימת דוגמה מוכנה שמגיעה עם הגרסה המעודכנת ולמי שחסר ניתן להוריד אותה מכאן כך שלא צריך להתאמץ יותר מידי.

בעזרת פרטוקול Http ושרת Web, נוכל לשלוט על הפינים בעזרת מבנה Url, לדוגמה נניח שנרצה להפוך את Pin 13 ל OutPut נקרא לכתובת במבנה מסויים שברגע שתגיע לשרת הוא יחתוך אותה ויפעל בהתאם כפי שניתן לראות בדוגמאות הבאות:

הגדרת הרגל כ Input / Output:
http://arduino.local/arduino/mode/13/output
כתיבת ערך לרגל דיגיטלית:
http://arduino.local/arduino/digital/13/1
קריאת ערך מרגל דיגיטלית:
http://arduino.local/arduino/digital/13
כתיבה ערך לרגל אנלוגית:
http://arduino.local/arduino/analog/2/128
קריאת ערך מרגל אנלוגית:
http://arduino.local/arduino/analog/2


אחרי שצרבנו את התוכנית, אפשר לעבור לתוכנית השניה שנכתוב Python שתדבר עם ה Bridge ותשלוט ברגליים על פי הצורך, במקרה הזה נתחבר בצורה מקומית, זה יתרון אדיר שמאפשר לנו לשלב את המעבדים בצורה פשוטה ולהנות מכל העולמות בו זמנית, נשתמש במספר כלים שיעזרו לנו בעבודה:
  • Putty - נתחבר ל Arduino Yun בעזרת SSH.
  • WinSCP - העברת קבצים בין המחשב האישי ל Arduino Yun.
נפתח Notepad ונרשום את הקוד הבא:

#Arduino Yun blink example using Bridge with Python
#proxytype.blogspot.com
#getting Thread function from Thread class
from threading import Thread

#add Libraries
import urllib2
import time

#selected Pins
PIN = 7

#set pins output/input
response = urllib2.urlopen('http://localhost/arduino/mode/' + str(PIN) + '/output')
print response.read()

def main(n):
    #flag
    Status = False
    while True:
if Status == False:
Status = True
response = urllib2.urlopen('http://localhost/arduino/digital/' + str(PIN) + '/1')
print response.read()
else:
Status = False
response = urllib2.urlopen('http://localhost/arduino/digital/' + str(PIN) + '/0')
print response.read()
time.sleep(n)
#start in new thread, send second to sleep
t = Thread(target=main, args=(1,))
t.start()



נשמור את הקובץ ונעביר אותו ל Yun בעזרת WinSCP, ואח"כ נתחבר ל Terminal בעזרת SSH ונריץ את התוכנית:



סרט לדוגמה



סיכום

הלוח הזה לוקח את כל העסק צעד אחד קדימה במחיר יחסית שפוי של 60$, ומאפשר לנו לכתוב פרוייקטים יותר מורכבים ועדיין להישאר באותה מסגרת נוחה של Arduino, בהמשך נראה כיצד להשתמש בספריות היעודיות של ה Yun שמאפשרות לגשת למשאבי ה Linux מבלי לעזוב את ה IDE.

יותר שכל באותו מקום...


יום שישי, 17 בינואר 2014

Arduino And EEPROM


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

דרישות

  • Arduino Uno
  • 24LC256 EEPROM
  • Wires
  • Breadboard




EEPROM - Electrically Erasable Programmable Read-Only Memory

אין ספק שהשם מפוצץ אבל בסופו של דבר מדובר ביחידת זיכרון שמאפשרת לשמור על המידע גם כאשר המכשיר כבוי, הרכיב שבחרתי עליו להדגים הוא 24LC256 שמאוד נפוץ במחיר 2 $ בלבד מאפשר לנו להרחיב את הזיכרון בעוד 256K ,הוא אינו נדיף בניגוד ל Ram ובנוסף הכתיבה והקריאה הן ברמת Bit בודד בניגוד לזיכרון Flash שלצורך שינוי ביט אחד יש לקרוא בלוק של מידע ,לטעון אותו לזיכרון ה Ram, לעשות את השינוי ולכתוב בחזרה ל Flash מה שהופך את העסק למסורבל אבל חיוני מאוד למידע בנפחים גדולים.

256K של זיכרון לא נדיף
הרגליים האנלוגיות (A5, A4) ב Arduino Uno מאפשרות לעבוד בתקשורת I2C Inter-Integrated Circuit שדומה מאוד ל SPI שראינו במאמר Arduino and MicroSD ההבדל העיקרי הוא שב SPI עבור כל רכיב נצטרך רגל אחת מה Arduino לעומת I2C שבו כל הרכיבים מתחברים לאותן כניסות בלוח ובקלות ניתן להוסיף עוד רכיבים, מדובר על 2 רגליים שבעזרתן מייצרים Bus הרגל הראשונה היא השעון, והשניה ל Data, לכל רכיב יש כתובת ייחודית שדרכה מתחברים בעזרת הממשק.

המון חיבורים עם 2 רגליים בלבד

קוד

החלטתי לתת דוגמה קצת יותר מורכבת מאשר כתיבה וקריאה של ערך בודד אלא לכתוב ולקרוא מחרוזות, ניתן לכתוב ולקרוא  16bytes  בלבד בכל פעם לכן יש להתקדם בכתובות בזיכרון בעזרת חלוקה ל Pages. 

#include <Wire.h>

//unique address for the eeprom 24LC256
#define eeprom1 0x50 
#define readblock 100
#define pageblock 16

//size of the message
unsigned char length = 0;
//receive data buffer
unsigned char rdata[readblock];

 
void setup(void)
{
  //example of parsable string
  unsigned char str_data[]={"{message:this is working! using EEPROM}\n"};

  Serial.begin(9600);

  //Active I2C interface
  Wire.begin();

  //writing  data to 24LC256
   writeData(str_data);
}

 void loop(){

    Serial.println("DATA READ");
 
    //reading data to 24LC256 
    readData(rdata,readblock);
    Serial.write(rdata,readblock);

    delay(1000);
}


void writeData( unsigned char * str_data)
{

  unsigned char pages = 0;
  unsigned char offset = 0;
  unsigned char index = 0;
  unsigned char counter = 0;

  //get the length of data
  length = getStrLength(str_data);
  //get the number of page to write
  pages = length / pageblock;

  //make the magic
  for(index = 0; index <= pages;index++)
  {
       //connecting to the device
       Wire.beginTransmission(eeprom1);
 
       //set the position of writing,
       Wire.write((int)((offset) >> 8));   //MSB -  Most significant bit
       Wire.write((int)((offset) & 0xFF)); // LSB - Least significant bit
     
       //total bytes writed to jump the next page address
       unsigned char i= 0;
     
       for(i= 0; i < pageblock;i++)
        {
                //writing the char to the memory unit.
                Wire.write((byte) str_data[counter]);
 
                //if counter equal data length quit!
                if(counter == length)
                      break;
                   
                 //increment the total counter of length
                 counter++;                
        }
   
       //end I2C transmission
        Wire.endTransmission();
     
        //move offset to the next page  
        offset += i;
     
        //give it some time...
        delay(10);
     
  }

}

 void readData(unsigned char* data, unsigned int length)
 {
 
   unsigned char offset = 0;
   unsigned char counter = 0;
 
   //start reading pages until new line break
  while(true)
  {
     //total bytes writed to jump the next page address 
     unsigned char i=0;
      Wire.beginTransmission(eeprom1);
   
      //set position of reading
      Wire.write((int)(offset >> 8));   //MSB -  Most significant bit
      Wire.write((int)(offset & 0xFF)); //LSB - Least significant bit
   
     //end I2C transmission
      Wire.endTransmission();

       //request data from device
      Wire.requestFrom(eeprom1,length);

      while(Wire.available())
      {
          //write char to position data
          data[counter] = Wire.read();
       
          //end of message!
          if(data[counter] == '\n')
          {
              return;
          }
       
         i++;
         counter++;
     }
   
     offset+=i;
     delay(10);
  }
}

 //get the length from chars array
 unsigned char getStrLength(unsigned char * data)
 {
   unsigned char str_len=0;
    do{ str_len++; } while(data[str_len]);
    return str_len;
 }



מבנה סופי



סיכום

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

שנה חמישית, ואו!


יום שבת, 21 בספטמבר 2013

Arduino MicroSD



עד עכשיו דגמנו חיישנים והעברנו את המידע דרך החיבור הסיראלי בחזרה למשתמש אבל זה לא מספיק, נניח שיש לנו חיישן שאנחנו רוצים לנטר אותו לאורך טווח ולאסוף עליו סטטיסטיקות ,אין מספיק שטח אחסון על ה Arduino שישמור לנו את המידע ולכן צריכים שטח אחסון חיצוני, אחת הדרכים הנפוצות היא לעבוד עם MicroSD Card Module , את שלי מצאתי ב DX במחיר של 4 דולר ולצורך הדוגמה אני אשתמש בו בשביל לשמור נתונים שמגיעים מחיישן טמפרטורה.


דרישות:

  • Arduino Uno
  • MicroSD Module
  • (MicroSD 4GB (FAT32 Limit
  • TMP36
  • Breadboard
  • Wires




Serial Peripheral Interface

ממשק ותיק להעברת נתונים בין רכיבים בניגוד לממשק ה Uart שמורכב סה"כ מ 2 חיבורים (RX,TX) , ב SPI נדרשים 4 חיבורים לפחות על מנת להשלים את ההתחברות וניתן לחבר עוד רכיבים על אותו ממשק, לכל רכיב שתומך ב  SPI יש 4 פינים שאותם מחברים ל (Master (Arduino ובעזרתו מנתבים את המידע בין הרכיבים השונים.
  • SCK - פעימת שעון מה Master.
  • MISO- Master In Slave Out - מידע שעובר מה Master ל Slave.
  • MOSI - Master Out Slave In - מידע שעובר מה Slave ל Master.
  • CS - Chip Select - בחירת הרכיב שאיתו מדבר ה Master, כמות החיבורים משתנה ב Master לפי כמות הרכיבים.
במקרה שנרצה לשלוח מידע לרכיב ספציפי נוריד את ה Chip Select של אותו רכיב ל LOW ובשאר הרכיבים ל HIGH על מנת שהתעלמו מהמידע, ניתן לשלוח את אותו מידע גם בצורה פרללית לכל הרכיבים  כשנוריד את ה Chip Select לכולם או להפך בשביל שהתעלמו. 


Serial Peripheral Interface


ב Arduino יש מספר פינים קבועים שדרכם מבצעים את ההממשקות ל SPI אבל הם עלולים להשתנות בין הדגמים ניתן לדעת אותם במדוייק באתר הרשמי של Arduino.





קוד

התוכנית עצמה מאוד פשוטה , דוגמים את החיישן בכל שנייה, אוספים את הנתונים ורושמים אותם לכרטיס ה SDcard, משתמשים בספריה מוכנה (SD.h) שבאה עם הסביבה של ה Arduino שמנהלת את שטח אחסון ומאפשרת לעבוד עם Filesystem מסוג FAT עד לנפח 4 GB.

#include <SD.h>

int tempPin = 0;
int csPin = 10;

void setup(){
  Serial.begin(9600);
  initSD();
}

void loop(){
  //get the milivolts
  float temp  = getVoltage(tempPin);

  float Celsius = 0;
  float Fahrenheit = 0;

  //convert the milivolts to Fahrenheint
  Fahrenheit = (((temp -.5)*100)*1.8)+32;
  
  //convert Fahrenheint to Celsius
  Celsius = ((Fahrenheit - 32) * 5 ) /9;
  
  //write values to SD card
  writeSD(Celsius,Fahrenheit);
  
  delay(1000);
}

//check if the chip select available
void initSD(){
   pinMode(csPin, OUTPUT);
    if (!SD.begin(csPin)) {
    Serial.println("Load SD failed!");
  }
  Serial.println("Load SD complete.");
}

//reading the analogpin and getting 
//the milivoltages.
float getVoltage(int pin)
{
  return (analogRead(pin) * .004882814);
}

void writeSD(int Celsius, int Fahrenheit){
  
  String str = "Celsius: " + String(Celsius) + " Fahrenheit: " + String(Fahrenheit);
  
  //try to write file
  File dataFile = SD.open("log.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.println(str);
    dataFile.close();
    Serial.println(str);
  }  
  else {
    Serial.println("error opening file");
  } 
  
}


מבנה סופי




סיכום

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

איזה שכלול... 





יום שבת, 7 בספטמבר 2013

OpenWRT - Custom Router Guide




לכל מי שיש Router מיותר זה מאמר בדיוק בשבילו, לאחרונה נתקלתי בנתב ישן בבית שמחוץ לעלות אבק הוא לא כל כך מועיל וחשבתי לעצמי האם ניתן לשפר אותו? או להתקין עליו מערכת חדשה? מסתבר שזה אפשרי בעזרת הפרויקט OpenWRT שמאפשר להתקין מערכת הפעלה של Linux ע"ג נתבים שונים ומגוונים, צריבת מערכת הפעלה חדשה על מכשירים סגורים של יצרנים עלולה להרוס את המכשיר כמו שתראו בהמשך.

OpenWRT

מערכת Linux Embedded שתומכת ברוב הארכיטקטורת מעבד שבשוק, מתאימה בעיקר למוצרים כמו Routers ומוצרי תקשורת אחרים, היא התחילה את דרכה בשנת 2004, היא הותאמה בעיקר לנתבים של LinkSys אבל עם הזמן התרחבה לנתבים מחברות שונות.

שימו לב!
  • לפני שאתם חושבים לשדרג את הנתב שלכם כדאי שתבדקו בטבלת התמיכה שנמצאת באתר ותוודאו שהנתב שלכם ברשימה.
  • התהליך שמוצג במאמר יכול להרוס את המכשיר ברשותכם ללא יכולת לשחזור ותיקון , אני לא אחראי על כל נזק שנגרם לנתב שלכם - ראו הוזהרתם!
לאחר שמצאנו את הנתב בטבלה ברוב המקרים יש הסבר מפורט איך להתקין את מערכת ההפעלה ואת ה BootLoader אם לא מצאתם הסבר כזה לא מומלץ להתקין את מערכת ההפעלה כי סביר להניח שזה לא יעבוד ותהרסו את המכשיר.


D-Link Dir-300 A



המתנדב לניסוי הוא נתב ישן של D-LINK עם 4 כניסות LAN, כניסת WAN ו WIFI, הוא מבוסס על מעבד MIPS במהירות 182 MHZ עם 4 MB של FLASH ו 16 MB של RAM.

שימו לב! - לכל נתב יש תהליך צריבה משלו חשוב מאוד לעבור אחרי ההוראות באתר OpenWRT ומומלץ לחפש במקורות נוספים באינטרנט.

לפני שנתחיל לעבוד על הנתב יש מספר תוכנות שמומלץ להכין מראש:
  • PUTTY - תוכנה להתחברות בפרוטוקולים שונים כמו Telnet, SSH ו Serial.
  • WINSCP - תוכנה להעברת קבצים בעזרת SSH.
  • TFTPD32 - תוכנה להעברת קבצים בפרוטוקל Trivial File Transfer Protocol.
  • Port Scanner - סריקה מהירה של פורטים על הנתב.

יש להוריד מספר קבצים מאתר OpenWRT:


תחילה יש להחליף את ה Bootloader המקורי (RedBoot) ל BootLoader של OpenWRT שנקרא DD-WRT, התהליך עצמו קצת מוזר נותנים למחשב כתובת סטטית 192.168.20.80 ומחברים אותו לכניסת ה WAN בנתב, מחברים את הנתב לחשמל ונפתח לנו חלון של כמה שניות שדרכו ניתן להתחבר לנתב בעזרת Telnet בכתובת 192.168.20.81 בפורט 9000, זה לא תמיד מצליח ולפעמים צריך לכבות ולהפעיל את הנתב מספר פעמים עד שנכנסים לאחר מכן מכניסים את הפקודה:

Redboot> load ap61.ram
Redboot> go.

חשוב מאוד שתוכנת ה TFTP תעבוד ותצביע לתיקייה עם הקבצים הנחוצים, ברגע הרצת הפקודה הנתב ינסה למשוך את הקבצים מהמחשב ובסיום יש להפעיל את הנתב מחדש לא לפני שננתק את המחשב מה WAN ונחבר אותו לאחד כניסות ה WAN ונגדיר את הכתובת 192.168.1.2, נעשה את אותו טריק ונפעיל את הנתב מחדש וננסה להתחבר לכתובת 192.168.1.1 בפורט 9000, לאחר שהתחברנו מחדש נריץ את הפקודות הבאות:

כניסה למצב כתיבה לזיכרון:
DD-WRT>fis init
About to initialize [format] FLASH image system - continue (y/n)? y
*** Initialize FLASH Image System
... Erase from 0xbffe0000-0xbfff0000: .
... Program from 0x807f0000-0x80800000 at 0xbffe0000: .

הגדרת TFTP:

DD-WRT>ip_address -h 192.168.1.2
IP: 192.168.1.1/255.255.255.0, Gateway: 0.0.0.0
Default server: 192.168.1.2


כתיבת ה ROM מה TFTP:

DD-WRT>load -r -b %{FREEMEMLO} ap61.rom
Using default protocol (TFTP)
Raw file loaded 0x80080000-0x800a8717, assumed entry at 0x80080000


כתיבת ה Bootloader באופן קבוע:

DD-WRT>fis create -l 0x30000 -e 0xbfc00000 RedBoot
An image named 'RedBoot' exists - continue (y/n)? y
... Erase from 0xbfc00000-0xbfc30000: ...
... Program from 0x80080000-0x800a8718 at 0xbfc00000: ...
... Erase from 0xbffe0000-0xbfff0000: .
... Program from 0x807f0000-0x80800000 at 0xbffe0000: .


הגדרת Bootp:

DD-WRT>fconfig bootp false
bootp: Setting to false
Update RedBoot non-volatile configuration - continue (y/n)? y
... Erase from 0xbffe0000-0xbfff0000: .
... Program from 0x80ff0000-0x81000000 at 0xbffe0000: . 



בסיום נריץ את הפקודה Reset ובפעם האחרונה שוב נתחבר בעזרת Telnet לכתובת 192.168.1.1 בפורט 9000, ונריץ את הפקודות הבאות:


כניסה למצב כתיבה לזיכרון:
DD-WRT>fis init
About to initialize [format] FLASH image system - continue (y/n)? y
*** Initialize FLASH Image System
... Erase from 0xbffe0000-0xbfff0000: .
... Program from 0x807f0000-0x80800000 at 0xbffe0000: .


הגדרת TFTP:

DD-WRT>ip_address -h 192.168.1.2
IP: 192.168.1.1/255.255.255.0, Gateway: 0.0.0.0
Default server: 192.168.1.2

טעינת קובץ מערכת ההפעלה לזיכרון

DD-WRT>load -r -b %{FREEMEMLO} openwrt-atheros-vmlinux.lzma
Using default protocol (TFTP)
Raw file loaded 0x80040800-0x801007ff, assumed entry at 0x80040800


כתיבת הקובץ לנקודה ספציפית בזיכרון:

DD-WRT>fis create -e 0x80041000 -r 0x80041000 vmlinux.bin.l7
... Erase from 0xbfc30000-0xbfcf0000: ............
... Program from 0x80040800-0x80100800 at 0xbfc30000: ............
... Erase from 0xbffe0000-0xbfff0000: .
... Program from 0x80ff0000-0x81000000 at 0xbffe0000: .

טעינת קובץ של ה File System  לזיכרון:

DD-WRT>load -r -b %{FREEMEMLO} openwrt-atheros-root.squashfs
Using default protocol (TFTP)
Raw file loaded 0x80040800-0x802207ff, assumed entry at 0x80040800''


כתיבת ה File System לזיכרון באופן קבוע:
DD-WRT>fis create rootfs
... Erase from 0xbfcf0000-0xbffe0000: ...............................................
... Program from 0x80040800-0x80220800 at 0xbfcf0000: ..............................
... Erase from 0xbffe0000-0xbfff0000: .
... Program from 0x80ff0000-0x81000000 at 0xbffe0000: .

הגדרת זמן טעינת ה Bootloader:

DD-WRT>fconfig boot_script_timeout 5


הגדרת טעינת Script בזמן שה Bootloader עולה:

DD-WRT>fconfig boot_script true
Run script at boot: true 

הגדרת הפקודה ב Script:

DD-WRT>fconfig
Run script at boot: true
Boot script:
Enter script, terminate with empty line
>> fis load -l vmlinux.bin.l7
>> exec
>>

הנתב יציג פרמטרים נוספים ובסיום יש לבצע Reset:

Boot script timeout (1000ms resolution): 5
Use BOOTP for network configuration: false
Gateway IP address: 192.168.1.1
Local IP address: 192.168.1.10
Local IP address mask: 255.255.255.0
Default server IP address: 192.168.1.228
Console baud rate: 9600
GDB connection port: 9000
Force console for special debug messages: false
Network debug at boot time: false
Update RedBoot non-volatile configuration - continue (y/n)? y
... Erase from 0xbffe0000-0xbfff0000: .
... Program from 0x80ff0000-0x81000000 at 0xbffe0000: .''

DD-WRT>reset

זהו אפשר לומר שסיימנו וכרגע על הנתב מותקנת מערכת הפעלה חדשה, נתחבר לנתב בעזרת Telenet לכתובת 192.168.1.1 הפעם בפורט הסטנדרטי (23), נוכל להגדיר סיסמא ,להתחבר בעזרת SSH וכמובן לנהל את הנתב בעזרת הדפדפן.





Brick Device

מה שראינו זה תהליך שכנראה קורה רק בתאוריה ובפועל העסק הולך ומסתבך, אחד הטעויות שעשיתי היא שהורדתי את הקבצים של הגרסה האחרונה מ OpenWRT וזו היתה טעות רצינית, מסתבר שהתקנתי גרסה חדשה מידי שלא ממש תואמת לנתב שגרמה לו לעשות Reset כל הזמן ולא היה ניתן להתקין עליו אף תוכנה, עשיתי Reflashing אבל זה רק עשה את זה יותר גרוע ולא הצלחתי להתחבר אליו בשום צורה, בקיצור הנתב נהפך ל Brick וההיתי בטוח שזה הסוף, אבל מסתבר ש D-LINK לא הורידה מהלוח את האפשרות להתחבר בעזרת חיבור סיראלי והפינים עדיין קיימים ,זו היתה הדרך היחידה להציל את המצב.


לאחד הפרוייקטים שלי רכשתי לוח Breakout Board מחברת Sparkfun שמחבר בין UART ל USB, מחירו בסביבות 15 דולר, מחברים את יציאת ה RX בנתב ל TX ב Breakout ואת ה TX בנתב ל RX ב Breakout כמובן לא לשכוח את ה GND ,מתחברים עם Putty ומתחילים לצרוב אותו מחדש.


מסתבר שהתקנתי את הגרסה Barrier Breaker אבל הגרסה המתאימה ביותר עבור אותו נתב היא Kamikaze לכן יש לעיין בקבצים באתר לפני ההתקנה.

מבנה סופי


סיכום:

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

לאתר הרשמי:

שדרגו בחוכמה!

יום שבת, 22 ביוני 2013

Arduino BlueTooth Guide




חשבתי לעצמי שאם כבר דיברנו על BlueTooth למה לא לשלב את Arduino בעניין, בעזרת Android נשלוט ב Arduino ונפעיל רכיבים עם חיבור סיראלי שעובר דרך ה BlueTooth, חיפשתי באינטרנט רכיב זול ואמין שיעשה את העבודה ומצאתי אותו ב  DX.com תמורת 6 דולר.



Wireless Bluetooth V2.0 RS232 TTL Transceiver Module

בסה"כ מדובר במודול מאוד פשוט, העבודה עם 4 פינים בלבד (1,2,12,13) , יש צורך להשתמש בספרייה NewSoftSerial על מנת שנוכל לדמות Uart נוסף עבור ה BlueTooth וצריך לעשות הצלבה בין ה RX וה TX של המודול מול הפינים שהגדרנו ב NewSoftSerial.


תמורת 2 דולר נוספים ניתן לקבל לוח שכולל את המודול, יחד עם פינים ו Led אדום שמהבהב שזה בהחלט משתלם ממקום שנבנה אותו בעצמנו.

שימו לב - המודול עובד על 3.3 V שימוש ב 5V עלול לשרוף אותו.

דרישות:
  • Arduino Uno / Nano
  • Wireless Bluetooth V2.0 RS232 TTL Transceiver Module
  • Wires
  • Android Tablet / Phone Support BlueTooth.
  • Servo


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



יש להגדיר את חוקי הדיבור בין ה Android ל Arduino, ההגדרה בקוד שאם מגיעה האות F ה Servo יתקדם קדימה ואם תגיע האות B ה Servo יתקדם אחורה בין כל בקשה ניכנס ל Delay של 25 ms על מנת לאפשר ל Servo לנוע.

קוד:

#include <NewSoftSerial.h>
#include <Servo.h> 

//break state
byte stateHold = false;
//forward state
byte stateForward = false;
//reverse state
byte stateReverse = false;

//commands: 
//F  = Servo move forward
//B = Servo move Backward
char FWDCMD = 'F';
char BWDCMD = 'B';

//Bluetooth section over software serial
//Arduino RX - 7 ,Arduino TX  - 6
NewSoftSerial bluetooth(7, 6);
byte b;

//Servo section
int servoPin = 3;
Servo myservo;

void setup() {
  //arduino serial for debugging
  Serial.begin(9600);   // opens serial port, sets data rate to 9600 bps
  Serial.flush();
  
  //attach servo to servo pin
   myservo.attach(servoPin);
   
  bluetooth.begin(9600);
  Serial.println("set bluetooth success");
}

void loop() {

  if (bluetooth.available()) {
    Serial.print("Android Send:");
    b = bluetooth.read();
    
    if((char)b == FWDCMD)
    {
        stateForward = true;
        stateHold = false;
        servoState();
        stateHold = true;
    
    }
    else if ((char)b == BWDCMD)
   {
       stateReverse = true;
        stateHold = false;
        servoState();
        stateHold = true;
   }   
   
    //print command in serial for debugging
    Serial.println((char)bluetooth.read(),BYTE);
    b = '\0';
  }
}


//change servo rotation by command
void servoState()
{
  if(stateHold == false)
    {
        myservo.attach(servoPin);
        if(stateForward == true)
        {
          stateReverse = false;
          myservo.write(0);
           delay(25);
           stateForward = false;
        }
        
        if(stateReverse == true)
        {
          stateForward = false;
           myservo.write(360);
           delay(25);
           stateReverse = false;
          
        }
        
         myservo.detach();
    }
}

מבנה סופי:



Android

אני לא אחזור על דברים מהמאמר הקודם אבל צריך להשים לב למספר דברים בקוד, קודם כל ה Android צריך למצוא את ה Device ואח"כ להתחבר אליו עם UUID שמייצג תקשורת סיראלית, לאחר מכן נפתח Socket בין המכשיר ל Device, מעבירים את פקודות הדיבור שנקבעו מראש שדרכם נתקשר עם ה Arduino שבסופו של דבר יגרום ל Servo לזוז, בנוסף למחלקה BTClient שמבוססת על AsyncTask אנחנו נשתמש בכלי מקבילי נוסף שנקרא Runnable על מנת שנוכל לתכנת את התנהגות הכפתורים.


קוד:

package com.proxytypeblog.arduinobtapp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageButton;

public class MainActivity extends Activity {

private static final String TAG = "Activity";
BluetoothAdapter mBluetoothAdapter;
BTClient _client;
BluetoothDevice mDevice;

boolean flag = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

boolean check = loadBlueTooth();
if (!check) {
Log.e(TAG, "Error to connect bluetooth");
}

setForwardButton();
setBackwardButton();
}

private void setBackwardButton() {
ImageButton btn_backward = (ImageButton) findViewById(R.id.btn_backward);
btn_backward.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
flag = true;
new Thread(new Runnable() {
public void run() {
while (flag) {
try {
//make sleep like arduino
Thread.sleep(25);
//char B for backward servo
_client.write("B");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
break;
case MotionEvent.ACTION_UP:
flag = false;
break;

default:
break;
}

return false;
}
});
}

private void setForwardButton() {
ImageButton btn_forward = (ImageButton) findViewById(R.id.btn_forward);

btn_forward.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
flag = true;

new Thread(new Runnable() {
public void run() {
while (flag) {
try {
//make sleep like arduino
Thread.sleep(25);
//char F for forward servo
_client.write("F");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
break;
case MotionEvent.ACTION_UP:
flag = false;
break;

default:
break;
}

return false;
}
});

}

private boolean loadBlueTooth() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
return false;
}

mBluetoothAdapter.startDiscovery();
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter
.getBondedDevices();

if (pairedDevices.size() > 0) {

for (BluetoothDevice device : pairedDevices) {

// the device i want to connect.
if (device.getName().contains("linvor"))
mDevice = device;

Log.d(TAG, device.getName());
}
}

// UUID service for serial
_client = new BTClient(mDevice, "00001101-0000-1000-8000-00805F9B34FB");
_client.execute("");

return true;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

private class BTClient extends AsyncTask<String, String, String> {
private final String TAG = "AsyncTask";
private BluetoothSocket mmSocket;
private BluetoothDevice mmDevice;
private BluetoothAdapter mBluetoothAdapter;
private InputStream mmInStream;
private OutputStream mmOutStream;
private UUID mmUUID;

// getting the device with application unique key
public BTClient(BluetoothDevice device, String CODE) {
mmUUID = UUID.fromString(CODE);
mmDevice = device;
BluetoothSocket tmp = null;

// getting the your own device adpater
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

// try to create a socket
try {
tmp = device.createRfcommSocketToServiceRecord(mmUUID);
} catch (IOException e) {
e.printStackTrace();
}

mmSocket = tmp;

}

@Override
protected String doInBackground(String... params) {

// if the our adapter on discovering, cancel it
if (mBluetoothAdapter.isDiscovering())
mBluetoothAdapter.cancelDiscovery();

try {
// make the connection and collect the stream
mmSocket.connect();
mmInStream = mmSocket.getInputStream();
mmOutStream = mmSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}

String message = "";
int bytes;
byte[] buffer = new byte[1];
// keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
message = new String(buffer, 0, bytes);
mmSocket.getInputStream();

} catch (IOException e) {
Log.e(TAG, "disconnected", e);
break;
}
}

return null;
}

// write message to outputstream
public void write(String msg) {

try {
byte[] buffer = msg.getBytes("US-ASCII");
if (mmOutStream != null)
mmOutStream.write(buffer);

} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}

@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}

}
}


ממשק:



סרט דוגמה:




קבצי מקור:

https://sourceforge.net/projects/arduinobluetoot/

סיכום:

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

בהצלחה...