ארדואינו לך לישון

pro-mini-battery

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

צריכת זרם טיפוסית של ארדואינו אונו היא 45mA מה שיתן לנו להפעיל אותו על בטריה בין 12 ל- 24 שעות שזה מעט מדי. כשאנחנו מפעילים בקר על בטריה אנחנו רוצים שהבטריה תספיק לפחות לכמה חודשים ובמקרה הטוב כמה שנים.

ארדואינו אונו

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

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

LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

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

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

או קיי עכשיו נשלח את הארדואינו לישון ונעיר אותו כל דקה להדליק ממסר.

#include "LowPower.h"

void setup() {

  pinMode(7, OUTPUT); // relay

}

void loop() {
  for (int i = 0; i < 8; i++){
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
  digitalWrite(7, HIGH);

  delay(1000); 

  digitalWrite(7, LOW);

  delay(1000); 

}

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

volatile boolean relay = false; 
#include "LowPower.h"
 
void setup() { 
  pinMode(13, OUTPUT); 
  digitalWrite(13, LOW); // turn off led to save power 
  pinMode(7, OUTPUT); // relay 
  pinMode(2, INPUT); // distance sensor
}

void relay_on(){ // interrupt function 
  relay = true; 
}

void loop() {
  attachInterrupt(digitalPinToInterrupt(2), relay_on, LOW); // when pin 2 is low turn on relay

  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // sleep forever

  detachInterrupt(digitalPinToInterrupt(2)); // remove interrupt to stop it from keep firing

  if(relay){
    digitalWrite(7, HIGH); 
  } else{ 
    digitalWrite(7, LOW); 
  } 
  relay = false; // change state back to false
}

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

uno-sleep-usb

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

בשביל זה נעקוף את המייצב וניתן כח ישירות לפין 5V ו GND. אסור בשום אופן לתת יותר מ 6V ורצוי לתת מתח של 3-5.5 וולט(LIPO 3.7V, שלוש בטריות 1.5V או 4 בטריות 1.2 NIMH). מה שניתן לפין זה יהיה המתח שבו הבקר וכל הרכיבים יעבדו עליו אז צריך לדעת מראש באיזה טווחי מתח עובדים הרכיבים. הארדואינו יעבוד עד שהבטריה תגיע לאזור 3V ואז יושבת.

 

uno-sleep-battery

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

עבודה עם 8MHz יכולה גם לעשות בעיות עם כל מיני תפקודים שונים וספריות. אם אתם רוצים אז אפשר לעקוב אחרי ההסבר הזה כדי להוריד את המהירות. צריך שני ארדואינו כדי לעשות את זה ולצרוב BOOTLOADER חדש 8MHz לארדואינו שאנחנו רוצים לשנות. ברוב המקרים עושים את זה לבקר שעובד לבד כדי להפטר מהגביש והקבלים.

  • לפי גליון הנתונים של ATMEL הבקר ATMEGA328P צריך לקבל מעל 4.5 וולט כשהוא רץ במהירות 16MHz. לפי בדיקות שלי גם 3 וולט מספיקים כדי להריץ אותו. עם 8MHz אפשר לרדת לאיזור ה 2 וולט.

ארדואינו פרו מיני

הארדואינו פרו מיני פותח על ידי חברת SPARKFUN והבקר שנמצא עליו הוא זהה לבקר שנמצא על ארדואינו אונו. הוא מגיע בשני דגמים 3.3V ו 5V ובוחרים את הדגם לפי הרכיבים שהוא אמור להתממשק איתם – אם מפעילים רכיבים 5V שהם נפוצים יותר בוחרים בדגם הזה ואם מפעילים רכיבי 3.3V אז בוחרים בדגם הזה.

הפרו-מיני 3.3V רץ במהירות 8MHz ואפשר להפעיל אותו על ידי בטריה LIPO 3.7V שהיא נפוצה מאוד לכן להפעלה על בטריה בדרך כלל בוחרים בדגם הזה. גם את לוח 5V אפשר להפעיל על ידי בטריה 3.7V אם מחברים מתח ישיר לבקר.

יש לו שני חיבורים של מתח חיצוני – RAW ו VCC. הראשון משתמש במייצב המתח שמוריד אותו למתח הרצוי לפי הדגם, ו VCC הוא חיבור ישיר לבקר. המייצב מתח של הפרו-מיני נחשב יעיל לכן הפעלה עם בטריה דרך המייצב היא אפשרית בהחלט.

יש לו שתי נורות אחת של כח ואחת של פין 13 ואפשר לעקור את שניהם עם פלייר או מספריים דבר שמוריד 5 מיליאמפר בערך. בתמונה זהו פרו-מיני שמחובר עם בטריית 3V לחיישן מגנטי מסוג REED וכל המעגל צורך 5-10 מיקרו אמפר בזמן שינה. מעגל כזה יכול להחזיק שנים עם בטריה.

pro-mini-battery

Adafruit Trinket

זהו כרטיס פיתוח קטנצ’יק שמבוסס על בקר ATtiny85. לבקר הזה יש רק 6 רגליים להפעלה וזכרון של 8KB. כשהוא רץ במהירות 8MHz הוא צורך בערך 10 מיליאמפר , והטרינקט שעובד על 3.3V הוא מצוין להפעלה על בטריה. הרגליים שלו יכולות לשמש כרגליים דיגיטליות ואנלוגיות, וגם אפשר לשייך אותן לפסיקות.

כדי להשכיב אותו לישון אי אפשר להשתמש בספריה שהשתמשנו עד עכשיו כי היא לא תומכת בבקר ATtiny85, אבל אפשר להשתמש בספרית השינה של AVR ולהשיג את אותה התוצאה. הקוד הבא שולח את הטרינקט לישון וברגע שהחיישן ריד סוגר מעגל הוא מתעורר ומדליק את נורת לד שעל הלוח לשתי שניות.

// code from : https://bigdanzblog.wordpress.com/2014/08/10/attiny85-wake-from-sleep-on-pin-state-change-code-example/
#include <avr/sleep.h> 
#include <avr/interrupt.h>
const int switchPin = 2;
const int statusLED = 1;

void setup() {
  pinMode(switchPin, INPUT);
  digitalWrite(switchPin, HIGH); 
  pinMode(statusLED, OUTPUT);
// Flash quick sequence so we know setup has started

 for (int k = 0; k < 10; k = k + 1) {

 if (k % 2 == 0) {

 digitalWrite(statusLED, HIGH); 

} else {

 digitalWrite(statusLED, LOW);

 } 
delay(250);
 } 
} 

void sleep() {
    GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts
    PCMSK |= _BV(PCINT2); // Use PB2 as interrupt pin
    ADCSRA &= ~_BV(ADEN); // ADC off 
    set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement
    sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT) 
    sei(); // Enable interrupts
    sleep_cpu(); // sleep
    cli(); // Disable interrupts 
    PCMSK &= ~_BV(PCINT2); // Turn off PB3 as interrupt pin 
    sleep_disable(); // Clear SE bit 
    ADCSRA |= _BV(ADEN); // ADC on
    sei(); // Enable interrupts 
    } 
    ISR(PCINT0_vect) { // This is called when the interrupt occurs/ }

void loop() {
    sleep();
    digitalWrite(statusLED, HIGH); 
    delay(2000);
    digitalWrite(statusLED, LOW); 
}

adafruit-trinket-battery

הבטריות מחוברות ישירות ל 5V בטרינקט ועוקפות את מייצב המתח, אבל בטרינקט מייצב המתח הוא מאוד יעיל אז אפשר גם לחבר אל רגל BAT שמורידה את המתח.  שוב פעם, כדי לחסוך עוד כמה מיליאמפר צריך להסיר את נורת הלד.

 

Atmega328P

הכי טוב לעבוד עם הבקר כ standalone – אין נורות אין מייצבים ואין שטויות. מורידים את המהירות שלו ל 8MHz ונותנים מתח בין 3V-5.5V . יש חשיבות ל P בסוף הדגם של הבקר – המשמעות של זה היא pico שבנוי במיוחד לעבודה במתחים נמוכים וחסכון באנרגיה.

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

#include "LowPower.h" 

void setup() { 
  pinMode(7, OUTPUT);// led 
  pinMode(2, INPUT_PULLUP); // tilt sensor
}

void relay_on(){ // interrupt function

 // do nothing

 }

void loop() { 
  attachInterrupt(digitalPinToInterrupt(2), relay_on, HIGH); // when pin 2 is low turn on relay
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // sleep forever
  detachInterrupt(digitalPinToInterrupt(2)); // remove interrupt to stop it from keep firing

  digitalWrite(7, HIGH); // turn on led 2 seconds 
  delay(2000); 
  digitalWrite(7, LOW);
  delay(100); // give time to attach interrupt 
}

atmega328p-battery

אפשר לראות שהבקר מקבל ישירות 4.8V ועובד במהירות 8MHz עם השעון הפנימי שלו ללא גביש חיצוני. 5uA של צריכת אנרגיה יכולה להספיק לשנים ומה שיקבע את התוצאה הסופית יהיה כל כמה זמן הבקר יתעורר, לכמה זמן הוא יהיה ער, ומה הוא יעשה בזמן הזה.

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

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *