ฉันจะทราบความถี่การสุ่มตัวอย่างได้อย่างไร


16

ฉันเริ่มสับสนเล็กน้อยเกี่ยวกับอัตราการสุ่มตัวอย่างและการรับส่งข้อมูล ฯลฯ ฉันมีรหัส Arduino นี้:

#include <eHealth.h>

extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;


byte serialByte;
void setup() {
  Serial.begin(9600);
}

void loop() { 
  while (Serial.available()>0){  
    serialByte=Serial.read();
    if (serialByte=='S'){        
      while(1){
        fanalog0=eHealth.getECG();  
        // Use the timer0 => 1 tick every 4 us
        time=(timer0_overflow_count << 8) + TCNT0;        
        // Microseconds conversion.
        time=(time*4);   
        //Print in a file for simulation
        //Serial.print(time);
        //Serial.print(" ");
        Serial.print(fanalog0,5);
        Serial.print("\n");

        if (Serial.available()>0){
          serialByte=Serial.read();
          if (serialByte=='F')  break;
        }
      }
    }
  }
}

เนื่องจากไม่มีการขัดจังหวะล่าช้าอัตราการสุ่มตัวอย่างคืออะไร มันขึ้นอยู่กับความเร็วของ Arduino ADC หรือไม่? เมื่อฉันเพิ่ม baudrate ฉันจะเพิ่มความถี่ในการสุ่มตัวอย่างหรือเพียงแค่อัตราที่ฉันส่งข้อมูลผ่านพอร์ตอนุกรมหรือไม่

คำตอบ:


21

ความเร็วนาฬิกา Arduino ADC ถูกตั้งค่าไว้ .. Arduino-1.5.5 \ hardware \ arduino \ avr \ cores \ arduino \ wiring.c

นี่คือส่วนที่เกี่ยวข้อง

#if defined(ADCSRA)
    // Set A/D prescale factor to 128
    // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
    // XXX: this will not work properly for other clock speeds, and
    // this code should use F_CPU to determine the prescale factor.
    sbi(ADCSRA, ADPS2);
    sbi(ADCSRA, ADPS1);
    sbi(ADCSRA, ADPS0);

    // Enable A/D conversions
    sbi(ADCSRA, ADEN);
#endif

สำหรับ Arduino 16 MHz นาฬิกา ADC ตั้งไว้ที่ 16 MHz / 128 = 125 KHz การแปลงแต่ละครั้งใน AVR ใช้เวลา 13 ADC นาฬิกาดังนั้น 125 KHz / 13 = 9615 Hz

นั่นคืออัตราการสุ่มตัวอย่างที่เป็นไปได้สูงสุด แต่อัตราการสุ่มตัวอย่างที่แท้จริงในแอปพลิเคชันของคุณขึ้นอยู่กับช่วงเวลาระหว่างการโทรติดต่อกันแบบต่อเนื่อง
เมื่อคุณอ่านผลลัพธ์และส่งผ่านพอร์ตอนุกรมคุณจะได้รับความล่าช้าที่เพิ่มขึ้นตามอัตราการรับส่งข้อมูลที่ลดลง อัตรา baud ที่ต่ำกว่าจะใช้เวลาในการส่งข้อมูลยาวเท่ากันและใช้เวลานานกว่าในการเรียกการแปลง ADC ครั้งถัดไป

อัตราการสุ่มตัวอย่างที่เกิดขึ้นจริงในแอปพลิเคชันของคุณสามารถกำหนดได้ด้วยการใช้ตัวดีบักหรือตัวจำลอง แต่วิธีที่ง่ายกว่าคือการสลับพินดิจิตอลทุกครั้งที่คุณทำการแปลงและวัดความถี่ที่ขาแบบดิจิทัลสลับ


นอกจากนี้เวลาระหว่างการประทับเวลาของฉันเพิ่มขึ้นจาก ~ 1300 ไปจนถึง ~ 16400 แน่นอนว่าพวกเขาควรจะอยู่เหมือนกันหรือไม่ นั่นคือ 9600 ที่ 115200 พวกเขาเพิ่มขึ้นเพียงประมาณ 1500 หลังจากเวลาผ่านไปนานมาก
user3284376

@ user3284376 เกี่ยวกับรหัสการประทับเวลาของคุณฉันคิดว่ามันไม่สามารถทำงานได้ตลอดเวลา (สามารถขัดจังหวะโดยการขัดจังหวะบางอย่างในเวลาที่ผิด) ฉันขอแนะนำให้คุณโพสต์คำถามเฉพาะเกี่ยวกับวิธีการกำหนดเวลาความแม่นยำสูงบน Arduino และวางส่วนที่เกี่ยวข้องของรหัสของคุณไว้ที่นั่น
jfpoilpret

7

ฉันต้องการได้รับอัตราการสุ่มตัวอย่างสูงสำหรับโครงการ ปรากฎว่าสามารถตั้งค่า ADPS2, ADPS1, ADPS0 บิตของการลงทะเบียน ADCSRA เพื่อรับอัตราการสุ่มตัวอย่าง 76923 s / s หรือ 76.8 ks / s แต่ระวังว่าฉันใช้ ADC ของ Arduino ในโหมดการทำงานฟรีบรรทัดต่อไปนี้ใช้ได้สำหรับฉัน

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void setup() {
// Set the Prescaler to 16 (16000KHz/16 = 1MHz)
// WARNING: Above 200KHz 10-bit results are not reliable.
//ADCSRA |= B00000100;
sbi(ADCSRA, ADPS2);
cbi(ADCSRA, ADPS1);
cbi(ADCSRA, ADPS0);

// Set ADIE in ADCSRA (0x7A) to enable the ADC interrupt.
// Without this, the internal interrupt will not trigger.
//ADCSRA |= B00001000;
sbi(ADCSRA,ADIE)
}

ที่ความถี่นี้ผลลัพธ์ 10 บิตตามปกติไม่น่าเชื่อถือ หมายความว่าการเพิ่มอัตราตัวอย่างจะลดความแม่นยำของผลลัพธ์ ดังนั้นฉันจะใช้ 8 บิตบนเท่านั้นเพราะที่ prescalar นี้ 8-bits บนมีความน่าเชื่อถือ คุณสามารถเข้าไปดูรายละเอียดเพิ่มเติมในหน้านี้เพื่อนหินนี้! เขาทำออสซิลโลสโคปอัตราตัวอย่างสูงโดยใช้ UNO http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/


3

แต่ละลูปที่คุณพิมพ์ 8 ตัวอักษรผ่านลิงค์อนุกรม 9600bps อักขระแต่ละตัวใช้เวลา 10 บิต (1 เริ่ม, 8 บิตสำหรับตัวละคร, 1 หยุด) นั่นหมายความว่าคุณสามารถผ่านลูปนี้ได้ ~ 120 ครั้ง / วินาที

analogRead()ฟังก์ชั่นสามารถลิ้มลองที่ประมาณ 9600 ครั้ง / วินาทีในทฤษฎีแนบเนียนมันเป็นเรื่องเกี่ยวกับ 8600 ครั้ง / วินาที

คุณกำลังถูกล้อมรอบด้วยการสื่อสารแบบอนุกรม


ดังนั้นเมื่อเพิ่มเป็น 115200 ให้ 1440 ครั้ง / วินาทีนั่นคืออัตราตัวอย่างหรือไม่
user3284376

ให้หรือรับใช่ คุณต้องจำไว้ว่า Serial ต้องการให้อีกฝ่ายตอบสนองดังนั้นคุณต้องพึ่งพาการตอบสนองของพีซี นี่ไม่ใช่การกำหนดดังนั้นคุณจะได้รับความกระวนกระวายใจ
Cybergibbons

คุณอยู่ในจุดสิ้นสุดของ Arduino ทุกอย่างดูดี แต่ใน Python ช้ากว่ามากฉันต้องทำอะไรเพื่อเพิ่มประสิทธิภาพของคอมพิวเตอร์
user3284376

คุณไม่จำเป็นต้องดูสิ่งนี้เป็นปัญหากับประสิทธิภาพแบบอนุกรมบนพีซี แต่คุณจะได้รับตัวอย่างได้อย่างไรจากการส่งข้อมูล
Cybergibbons

1
@Cybergibbons - ไม่เนื่องจากนี่เป็นการทำงานบน Uno ที่มีการแยก USB และซีเรียลออกจากกันจึงไม่มีการพึ่งพาพีซีนอกเหนือจากการออกอักขระ 'S' และไม่ออก 'F' ร่างที่โพสต์ที่นี่และแพลตฟอร์มที่ทำงานจะมีความสุขที่จะโยนข้อมูลอนุกรมที่ไมโคร USB-serial สหาย, ลืมเลือนสุ่มสี่สุ่มห้าหากสิ่งนั้นหรือสิ่งอื่นใดที่ปลายอีกด้านของ USB กำลังดำเนินการอยู่
Chris Stratton

3

การส่ง 11 บิตผ่านอนุกรมที่ baud ของ 9600 แต่สำหรับการสุ่มตัวอย่างฉันเก็บไว้ในอาร์เรย์ที่มีความล่าช้าน้อยที่สุดเท่าที่จะเป็นไปได้จากนั้นเมื่อเสร็จแล้วฉันจะส่งมันผ่านพอร์ตอนุกรมเพื่ออ่านสคริปต์ไพ ธ อน ฉันทำสิ่งนี้เพื่อ FFT โดยใช้ matplotlib ฉันฟังสัญญาณ 0-5V จากนั้นโดยไม่ใช้ฟังก์ชั่น delay () ฉันจะเก็บค่า analogRead () ไว้ในอาร์เรย์นั้น ในเสี้ยววินาทีการอ่านจะเสร็จสิ้นจากนั้นการถ่ายโอนข้อมูลอนุกรมจะเริ่มขึ้น เมื่อฉันสอบเทียบความถี่อินพุตโดยใช้ tone () จาก Arduino ที่เชื่อมต่ออีกตัวฉันรู้ว่าฉันต้องหารดัชนีด้วย 8915 เพื่อให้ได้ความถูกต้องภายใน 0.1 Hz เนื่องจากจะต้องหารด้วยความถี่ของการสุ่มตัวอย่างเพื่อให้ได้ช่วงดัชนีที่เหมาะสมฉันเดาว่าความถี่การสุ่มตัวอย่าง Arduino (อย่างน้อยฉันกับรหัสของฉัน) คือ 8915Hz


1

อ้างถึงส่วนที่เกี่ยวกับความแตกต่างระหว่างอัตราตัวอย่างและอัตราการรับส่งข้อมูล

Sample Rate คือความถี่ที่อุปกรณ์ (arduino) สามารถสร้างการเป็นตัวแทนแบบดิจิตอลของค่าอนาล็อกที่เข้ามา

อัตรารับส่งข้อมูลคืออัตราที่ข้อมูลถูกถ่ายโอนในช่องทางการสื่อสาร มันอธิบายอัตราการสื่อสารระหว่างไมโครคอนโทรลเลอร์กับโลกภายนอก (คอมพิวเตอร์)

ฉันจะแนะนำลิงก์ electronics_stack_exchange นี้ /electronics/135056/sampling-rate-data-rate-and-bandwidth


0

8915Hz - ใกล้มากถึง 125000/14 ~ = 8928.6 ฉันเดาเริ่มต้นว่าต้องใช้ช่องว่างหนึ่งช่องระหว่างการแปลงที่อยู่ติดกันหนึ่งนาฬิกา ADC สำหรับการสุ่มตัวอย่างและนาฬิกา ADC 13 ตัวสำหรับการแปลงตัวเอง ข้อผิดพลาดเล็กน้อยอาจมีผลต่อแหล่งสัญญาณนาฬิกาที่ไม่สมบูรณ์ของ Arduino ฉันยังไม่แน่ใจ หัวข้อนี้เป็นจริงสำหรับฉันแล้วเนื่องจากข้อมูลตัวอย่างจะต้องป้อนตัวกรองดิจิทัล


1
ฉันไม่แน่ใจว่าคุณหมายถึงอะไรเมื่อคุณพูดว่า "หัวข้อนี้เป็นเรื่องจริงสำหรับฉันในขณะนี้เนื่องจากข้อมูลตัวอย่างจะต้องป้อนตัวกรองดิจิทัล" คุณมีปัญหาที่คล้ายกันหรือไม่?
VE7JRO

การแปลงแต่ละครั้งจะเริ่มต้นที่ขอบของนาฬิกา ADC และรอบนาฬิกา ADC อย่างน้อยหนึ่งรอบจะหายไปจากการเรียกใช้รหัส ใช่ 8928.6 Hz เป็นวิธีที่เร็วที่สุดที่คุณจะได้รับจากการโทรanalogRead()เป็นวงแคบเทียบกับ 9615.4 Hz ที่สม่ำเสมอมากในโหมดวิ่ง
Edgar Bonet
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.