খুব গভীর ঘুমের মধ্যে এটিমেগ 328 রাখুন এবং সিরিয়াল শুনবেন?


13

আমি এটিমেগা 328 এর স্লিপ অপশনগুলি অনুসন্ধান করেছি এবং এটি সম্পর্কে কয়েকটি নিবন্ধ পড়েছি এবং আরও বিকল্প আছে কিনা তা আমি বুঝতে চাই।

সুতরাং আমি যতটা সম্ভব কম স্রোত পেতে চাই, যাতে 100uA এর চেয়ে কম যে কোনও কিছু ভাল হয় - যতক্ষণ না আমি জারেটের জন্য ইউআরটি শুনতে এবং বাধা দিতে পারি।

আমি এটিএমগা 328 পি সহ একটি কাস্টম পিসিবি (ইউএনও নয়) ব্যবহার করছি।

গভীর ঘুমে চিপ সেট করা:

 set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
 sleep_enable();
 sleep_cpu ();

এটা ঘুম ভেঙ্গে যাবে না সিরিয়াল যোগাযোগ সঙ্গে, অনুযায়ী এই

IDLEসিরিয়াল শোনার জন্য আপনাকে এটি মোডে রাখতে হবে , তবে এটি কয়েক এমএ-ব্যয় করতে পারে।

আমি এই লিঙ্কটি পেয়েছি যেখানে আপনি হার্ডওয়্যারে সিরিয়ালটি বিঘ্নিত হয়ে সংযোগ করতে পারবেন - যা বিপজ্জনক যাতে আপনার তথ্য আলগা করতে পারে এবং তদতিরিক্ত, আমার এই 2 টি বাধা পিনের প্রয়োজন।

আমি গ্যামনের এই নিবন্ধটিও পড়েছি , যেখানে আপনি কিছু জিনিস অক্ষম করতে পারেন, যাতে আপনি খুব কম শক্তি দিয়ে আইডিএল ঘুম পেতে পারেন - তবে আপনি এ থেকে কীভাবে পাবেন তা তিনি উল্লেখ করেননি:

 power_adc_disable();
      power_spi_disable();
      power_timer0_disable();
      power_timer1_disable();
      power_timer2_disable();
      power_twi_disable();

সুতরাং, নীচের অংশে, কোনও বিকল্প নেই, কমপক্ষে 0.25mA এর চেয়ে কম পাওয়ার জন্য, এবং সিরিয়াল বন্দরটি শুনতে, কোনও হার্ডওয়্যার কারসাজি ছাড়াই? উদাহরণস্বরূপ, দীর্ঘ সিরিয়াল ডেটা ইনপুট দিয়ে জাগ্রত করবেন ?


1
@ নিক অলেক্সিভ এটি একটি এটিমেগ 328 প্রশ্ন যা আরডুইনো এক নয়, কারণ এটি চিড়ির সাথে সরাসরি অর্ডিনো স্তরের নীচে ডিল করে। ইতিমধ্যে অনুচিত স্থানান্তর বন্ধ করুন!
ক্রিস স্ট্রাটন

1
কষ্টসহকারে। ঘুম থেকে আরডুইনো জাগ্রত করতে চাইলে সত্যই তা খারিজ করা যায় না কারণ এটিতে এটিমেগ 328 চিপ রয়েছে। এই হারে আপনি আরডুইনোস সম্পর্কিত সমস্ত প্রশ্ন EE সাইটে ফিরে আসতে সক্ষম হবেন ।
নিক গ্যামন

উত্তর:


11

আমরা তৈরি একটি বোর্ড এটি করে।

  • আরএক্স পিনটি INT0 এ তারযুক্ত
  • কীভাবে আরএক্স লাইন চালিত হয় তার উপর নির্ভর করে ইনপুট বা ইনপুট পুলআপে সেট INT0 পিন
  • ঘুমের সময়, INT0 নিম্ন স্তরের বাধা সক্ষম হয়

    //Clear software flag for rx interrupt
    rx_interrupt_flag = 0;
    //Clear hardware flag for rx interrupt
    EIFR = _BV(INTF0);
    //Re-attach interrupt 0
    attachInterrupt(INT_RX, rx_interrupt, HIGH);
    
  • INT0 বিঘ্নিত পরিষেবা রুটিন একটি পতাকা সেট করে এবং বাধা নিষ্ক্রিয় করে

    void rx_interrupt()
    {
        detachInterrupt(INT_RX);
        rx_interrupt_flag = 1;
    }
    
  • জাগ্রত নেওয়ার সময়, আমরা পতাকাটি পরীক্ষা করে দেখি (অন্যান্য বিঘ্নিত উত্স রয়েছে)

জিনিসগুলির কমস সাইডে আমরা একটি বার্তা প্রোটোকল ব্যবহার করি যার একটি প্রারম্ভিক অক্ষর >এবং শেষ অক্ষর রয়েছে \r। যেমন >setrtc,2015,07,05,20,58,09\r। এটি বার্তাগুলি হারানোর বিরুদ্ধে কিছু প্রাথমিক সুরক্ষা দেয় কারণ আগত অক্ষরগুলি >প্রাপ্ত না হওয়া পর্যন্ত প্রক্রিয়া করা হয় না । ডিভাইসটি জাগ্রত করতে আমরা সংক্রমণের আগে একটি ডামি বার্তা প্রেরণ করি। একটি একক চরিত্র এটি করবে, কিন্তু আমরা >wakeup\rhehe প্রেরণ ।

নতুন বার্তাগুলির ক্ষেত্রে শেষ বার্তাটি পাওয়ার পরে ডিভাইসটি 30 সেকেন্ডের জন্য জাগ্রত থাকে। কোনও নতুন বার্তা পেলে 30 সেকেন্ডের টাইমারটি পুনরায় সেট করা হয়। পিসি ইন্টারফেস সফ্টওয়্যারটি ব্যবহারকারীকে কনফিগারেশন ইত্যাদির জন্য সংযুক্ত থাকা অবস্থায় ডিভাইসটিকে সচেতন রাখতে প্রতি সেকেন্ডে একটি ডামি বার্তা প্রেরণ করে

এই পদ্ধতিটি একেবারে কোনও সমস্যা দেয় না। কয়েকটি পেরিফেরাল সহ বোর্ড ঘুমন্ত অবস্থায় প্রায় 40uA ব্যবহার করে। এটিএমটিগা 328 পি দ্বারা ব্যবহৃত প্রকৃত বর্তমান সম্ভবত 4uA এর কাছাকাছি।

হালনাগাদ

ডেটাশিটটি দেখলে বোঝা যায় যে আরএক্স পিনটি পিন চেঞ্জ ইন্টারপ্রেট পিন 16 (পিসিআইএনটি 16)

এভাবে তার ছাড়া অন্য পদ্ধতি হতে পারে

  • ঘুমানোর আগে: পিসিআইএনটি 16 এর জন্য পিসিএমএসকে 2-তে পোর্ট চেঞ্জ ইন্ট্র্রেন্টন মাস্ক বিট সেট করুন, পিসিআইএফআর-তে পিন চেঞ্জ পোর্ট 2 পতাকা সাফ করুন, পিসি পরিবর্তন পোর্ট 2 ইন্টারপ্রেট (পিসিআইএনটি 16-পিসিআইএনটি 23) সক্ষম করুন পিসিআইসিআর-তে পিসিআইই 2 স্থাপন করে।

  • পিন পরিবর্তন পোর্ট 2 বাধাগুলির জন্য একটি আইএসআর সেটআপ করুন এবং আগের মতো চালিয়ে যান।

পোর্ট পরিবর্তন বাধাগুলি সহ একমাত্র সতর্কতা হ'ল এই বন্দরের জন্য সক্ষম হওয়া 8 টি পিন জুড়ে বাধা ভাগ করা হয়। সুতরাং আপনি যদি বন্দরের জন্য একাধিক পিন পরিবর্তন সক্ষম করে থাকেন তবে আপনাকে নির্ধারণ করতে হবে কোনটি আইএসআর-এ বাধা দেয়। আপনি যদি সেই বন্দরে অন্য কোনও পিন পরিবর্তন বিঘ্ন ব্যবহার না করেন তবে এটি কোনও সমস্যা নয় (এই ক্ষেত্রে PCINT16-PCINT23)

আদর্শভাবে এইভাবেই আমি আমাদের বোর্ডটি ডিজাইন করতাম তবে আমাদের কী কাজ হয়।


অনেক ধন্যবাদ . হার্ডওয়্যার ট্রিকস ছাড়া আর কোন উপায় নেই ??? সুতরাং আপনি কেবল 1 টি লাইনের সাথে rx ইন্ট0 / ইনট 1 এ সংযুক্ত করবেন ??
নির্দোষ

1
প্রকৃতপক্ষে আমি কেবল ডেটা শীটটিতে একটি নজর রেখেছি এবং আপনি পিন পরিবর্তন অন্তরায় ব্যবহার করতে সক্ষম হতে পারবেন
জ্যামিতিকাল

ধন্যবাদ, ভিন্ন কি হবে? যাইহোক আমি ইন্ট 1 এ আরএক্স সাথে জেগে উঠতে হবে?
কর্নেলিয়াস

আপনার কেবলমাত্র 1 টি বাধা পিন প্রয়োজন। আমি উপরে আরও কিছু পোস্ট করেছি - আপনি পিন পরিবর্তন বাধা হিসাবে আরএক্স পিনটি ব্যবহার করতে পারেন। আমি এটি করিনি যদিও এখানে কয়েকটি ক্যাচ হতে পারে সম্ভবত ঘুমের আগে আপনাকে আরএক্স অক্ষম করতে হবে / পিন পরিবর্তনটি সক্ষম করতে হবে এবং পিন পরিবর্তনটি অক্ষম করতে হবে / জাগানোর পরে আরএক্স সক্ষম করতে হবে
জ্যামিতিকাল

ধন্যবাদ, আমি নিশ্চিত না যে শুধু আরএক্সকে INT1 এর সাথে সংযুক্ত করার ক্ষেত্রে কেন সমস্যা হওয়া উচিত, ইনট 1 হওয়ার সাথে সাথে বাধা নিষ্ক্রিয় করা এবং ঘুমাতে যাওয়ার পরে আবার সক্ষম করে দেওয়ার চেয়ে উচ্চে বাধা স্থাপন করুন?
কর্নেলিয়াস

8

নীচের কোডটি যা জিজ্ঞাসা করছে তা অর্জন করে:

#include <avr/sleep.h>
#include <avr/power.h>

const byte AWAKE_LED = 8;
const byte GREEN_LED = 9;
const unsigned long WAIT_TIME = 5000;

ISR (PCINT2_vect)
{
  // handle pin change interrupt for D0 to D7 here
}  // end of PCINT2_vect

void setup() 
{
  pinMode (GREEN_LED, OUTPUT);
  pinMode (AWAKE_LED, OUTPUT);
  digitalWrite (AWAKE_LED, HIGH);
  Serial.begin (9600);
} // end of setup

unsigned long lastSleep;

void loop() 
{
  if (millis () - lastSleep >= WAIT_TIME)
  {
    lastSleep = millis ();

    noInterrupts ();

    byte old_ADCSRA = ADCSRA;
    // disable ADC
    ADCSRA = 0;  
    // pin change interrupt (example for D0)
    PCMSK2 |= bit (PCINT16); // want pin 0
    PCIFR  |= bit (PCIF2);   // clear any outstanding interrupts
    PCICR  |= bit (PCIE2);   // enable pin change interrupts for D0 to D7

    set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
    power_adc_disable();
    power_spi_disable();
    power_timer0_disable();
    power_timer1_disable();
    power_timer2_disable();
    power_twi_disable();

    UCSR0B &= ~bit (RXEN0);  // disable receiver
    UCSR0B &= ~bit (TXEN0);  // disable transmitter

    sleep_enable();
    digitalWrite (AWAKE_LED, LOW);
    interrupts ();
    sleep_cpu ();      
    digitalWrite (AWAKE_LED, HIGH);
    sleep_disable();
    power_all_enable();

    ADCSRA = old_ADCSRA;
    PCICR  &= ~bit (PCIE2);   // disable pin change interrupts for D0 to D7
    UCSR0B |= bit (RXEN0);  // enable receiver
    UCSR0B |= bit (TXEN0);  // enable transmitter
  }  // end of time to sleep

  if (Serial.available () > 0)
  {
    byte flashes = Serial.read () - '0';
    if (flashes > 0 && flashes < 10)
      {
      // flash LED x times 
      for (byte i = 0; i < flashes; i++)
        {
        digitalWrite (GREEN_LED, HIGH);
        delay (200);  
        digitalWrite (GREEN_LED, LOW);
        delay (200);  
        }
      }        
  }  // end of if

}  // end of loop

সিরিয়াল ডেটা কখন উপস্থিত হবে তা লক্ষ করার জন্য আমি আরএক্স পিনে একটি পিন-পরিবর্তন বাধা ব্যবহার করেছি। এই পরীক্ষায় 5 সেকেন্ড পরে কোনও তত্পরতা না থাকলে বোর্ড ঘুমাতে যায় ("জাগ্রত" এলইডি চলে যায়)। আগত সিরিয়াল ডেটা বোর্ডকে জাগাতে পিন-পরিবর্তন বাধা দেয়। এটি একটি সংখ্যার সন্ধান করে এবং সেই সংখ্যাটি "সবুজ" এলইডি জ্বলজ্বল করে।

বর্তমানের পরিমাপ

5 ভি-তে চালানো, আমি ঘুমানোর সময় প্রায় 120 এনএ বর্তমানের পরিমাপ করেছি (0.120 µA)।

জাগরণ বার্তা

তবে একটি সমস্যা হ'ল প্রথম আগমনকারী বাইটটি এই কারণে হারিয়ে গেছে যে সিরিয়াল হার্ডওয়্যারটি Rx (স্টার্ট বিট) এর একটি পতন স্তর প্রত্যাশা করে যা এটি পুরোপুরি জাগ্রত হওয়ার সময় ইতিমধ্যে পৌঁছেছে।

আমি প্রস্তাব দিচ্ছি (জ্যামিতিকের জবাব হিসাবে) আপনি প্রথমে একটি "জাগ্রত" বার্তা প্রেরণ করুন এবং তারপরে অল্প সময়ের জন্য বিরতি দিন । বিরতি হ'ল হার্ডওয়্যারটি জাগ্রত বার্তার অংশ হিসাবে পরবর্তী বাইটটি ব্যাখ্যা করে না তা নিশ্চিত করা to এর পরে এটি ঠিকঠাক কাজ করা উচিত।


যেহেতু এটি একটি পিন-পরিবর্তন বিঘ্নিত ব্যবহার করে অন্য কোনও হার্ডওয়্যার প্রয়োজন হয় না।


সফ্টওয়্যারসিরাল ব্যবহার করে সংশোধিত সংস্করণ

নীচের সংস্করণটি সিরিয়ালে প্রাপ্ত প্রথম বাইট সফলভাবে প্রক্রিয়া করে। এটি এর দ্বারা করে:

  • সফটওয়্যারসিল ব্যবহার করে যা পিন-পরিবর্তন বিঘ্ন ব্যবহার করে। প্রথম সিরিয়াল বাইটের শুরু বিটের কারণে যে বিঘ্ন ঘটে তা প্রসেসরকে জাগায়।

  • ফিউজ সেট করা যাতে আমরা ব্যবহার করি:

    • অভ্যন্তরীণ আরসি দোলক
    • বিওডি অক্ষম
    • ফিউজগুলি হ'ল: নিম্ন: 0xD2, উচ্চ: 0xDF, প্রসারিত: 0xFF

ফারো দ্বারা একটি মন্তব্যে অনুপ্রাণিত হয়ে এটি প্রসেসরটিকে 6 টি ঘড়ির চক্র (750 এনএস) এ জাগতে দেয়। 9600 বাউডে প্রতি বিট সময় 1/9600 (104.2 µs) হয় তাই অতিরিক্ত বিলম্ব তুচ্ছ।

#include <avr/sleep.h>
#include <avr/power.h>
#include <SoftwareSerial.h>

const byte AWAKE_LED = 8;
const byte GREEN_LED = 9;
const unsigned long WAIT_TIME = 5000;
const byte RX_PIN = 4;
const byte TX_PIN = 5;

SoftwareSerial mySerial(RX_PIN, TX_PIN); // RX, TX

void setup() 
{
  pinMode (GREEN_LED, OUTPUT);
  pinMode (AWAKE_LED, OUTPUT);
  digitalWrite (AWAKE_LED, HIGH);
  mySerial.begin(9600);
} // end of setup

unsigned long lastSleep;

void loop() 
{
  if (millis () - lastSleep >= WAIT_TIME)
  {
    lastSleep = millis ();

    noInterrupts ();

    byte old_ADCSRA = ADCSRA;
    // disable ADC
    ADCSRA = 0;  

    set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
    power_adc_disable();
    power_spi_disable();
    power_timer0_disable();
    power_timer1_disable();
    power_timer2_disable();
    power_twi_disable();

    sleep_enable();
    digitalWrite (AWAKE_LED, LOW);
    interrupts ();
    sleep_cpu ();      
    digitalWrite (AWAKE_LED, HIGH);
    sleep_disable();
    power_all_enable();

    ADCSRA = old_ADCSRA;
  }  // end of time to sleep

  if (mySerial.available () > 0)
  {
    byte flashes = mySerial.read () - '0';
    if (flashes > 0 && flashes < 10)
      {
      // flash LED x times 
      for (byte i = 0; i < flashes; i++)
        {
        digitalWrite (GREEN_LED, HIGH);
        delay (200);  
        digitalWrite (GREEN_LED, LOW);
        delay (200);  
        }
      }        
  }  // end of if

}  // end of loop

ঘুমানোর সময় বিদ্যুত ব্যবহার 260 এনএ (0.260 µA) হিসাবে পরিমাপ করা হয় যাতে প্রয়োজন হয় না তখন এটি খুব কম খরচ হয়।

নোট করুন যে ফিউজগুলি সেটির মতো সেট করে প্রসেসরটি 8 মেগাহার্টজ এ চলে। সুতরাং আপনাকে সেই বিষয়ে আইডিই বলতে হবে (উদাঃ বোর্ডের ধরণ হিসাবে "লিলিপ্যাড" নির্বাচন করুন)। এইভাবে বিলম্ব এবং সফটওয়্যারসরিয়াল সঠিক গতিতে কাজ করবে।


@ নিকগ্যামন আপনাকে অনেক ধন্যবাদ! আমি এটি ইতিমধ্যে করেছি এবং এটি কাজ করে। আমরা প্রতিদিন ব্যবহার করি এমন অন্যান্য পণ্যগুলিতে কি সেই উপায়টি কি সাধারণ, বা কম শোওয়ার এবং শোওয়ার অন্যান্য উপায় রয়েছে? (গভীর এমনিউতে সমস্ত এমসিইউর ক্যান্ট শুনতে পায় না?)
কার্নেলিয়াস

আমি ডাটাশিটটি পড়ছিলাম এবং এটিতে বলা হয়েছে যে অভ্যন্তরীণ দোলক ব্যবহার করার সময়, চিপটি শুরু করার জন্য কেবল 14 টি ঘড়ির চক্র প্রয়োজন, যদি বিডির ব্যবহার হয়। যদি পাওয়ার উত্স সর্বদা আপ থাকে (ব্যাটারি), তবে এটি বিওডি ছাড়াও ব্যবহার করা যেতে পারে? অবশ্যই চশমা লঙ্ঘন। এটি আগত ইউআরটি প্রান্তের খুব শীঘ্রই চিপটি নিয়ে আসবে, তবে এখনও আমি নিশ্চিত না যে এটি প্রথম বাইটটি ধরা যথেষ্ট হবে be
Faro

হ্যাঁ, ১৪ টি ঘড়ির চক্র দীর্ঘ নয়, তবে সম্ভবত ইউআরটি এখনও প্রান্তটি মিস করবে (সর্বোপরি প্রসেসরের পরিবর্তনটি লক্ষ্য করার পরে প্রান্তটি হবে)। সুতরাং এটি প্রান্তের খুব শীঘ্রই শুরু হলেও এটি এখনও এটি মিস করতে পারে।
নিক গ্যামন

কিছুটা পরীক্ষা নির্দেশ করে যে (এমনকি বিওড সক্ষম করেও) এটি কাজ করে না। অগ্রণী প্রান্তটি (স্টার্ট বিট) লক্ষ্য করার জন্য প্রসেসরের জাগ্রত হওয়া দরকার এবং এটি পাওয়ার পরে এটি শক্তিশালী করা (খুব শীঘ্রই পরে হলেও) কাজ করে না।
নিক দম্ভোক্তি

14 ঘড়ির চক্রটি পুনরায় সেট করার পরে। পাওয়ার-ডাউন করার পরে আপনার কেবল 6 টি চক্র দরকার, যদি আপনি অভ্যন্তরীণ আরসি দোলক ব্যবহার করেন। অতিরিক্ত উদাহরণ কোড দেখুন।
নিক গ্যামন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.