สารบัญ:

เครื่องกำเนิดคลื่นไซน์ 3 เฟสตาม Arduino เนื่องจาก: 5 ขั้นตอน
เครื่องกำเนิดคลื่นไซน์ 3 เฟสตาม Arduino เนื่องจาก: 5 ขั้นตอน

วีดีโอ: เครื่องกำเนิดคลื่นไซน์ 3 เฟสตาม Arduino เนื่องจาก: 5 ขั้นตอน

วีดีโอ: เครื่องกำเนิดคลื่นไซน์ 3 เฟสตาม Arduino เนื่องจาก: 5 ขั้นตอน
วีดีโอ: สัญญาณ pwm คืออะไร ? 2024, กรกฎาคม
Anonim
เครื่องกำเนิดคลื่นไซน์ 3 เฟสขึ้นอยู่กับ Arduino Due
เครื่องกำเนิดคลื่นไซน์ 3 เฟสขึ้นอยู่กับ Arduino Due

จุดประสงค์ของการแชร์นี้คือเพื่อช่วยคนที่พยายามใช้ Due ให้มีประสิทธิภาพมากขึ้น + ขาดการอ้างอิง + แผ่นข้อมูลที่ไม่เป็นประโยชน์

โครงการนี้สามารถสร้างคลื่นไซน์ได้สูงสุด 3 เฟส @ 256 ตัวอย่าง/รอบที่ความถี่ต่ำ (<1kHz) และ 16 ตัวอย่าง/รอบที่ความถี่สูง (สูงสุด 20kHz) ซึ่งดีพอที่จะทำให้เรียบโดย LPF ธรรมดาและ เอาต์พุตเกือบจะสมบูรณ์แบบ

ไฟล์แนบไม่ใช่เวอร์ชันสุดท้ายของฉัน เพราะฉันเพิ่มคุณสมบัติเพิ่มเติมบางอย่าง แต่แกนหลักเหมือนกันกับนั้น หมายเหตุ ตัวอย่าง/รอบถูกตั้งค่าต่ำกว่าข้อความสั่งด้านบน

เนื่องจากความจุของ CPU ถูกขยายให้ใหญ่สุดผ่านวิธีการที่แสดงในไฟล์แนบ ฉันจึงใช้ Arduino Uno เป็นหน่วยควบคุม ซึ่งใช้การขัดจังหวะภายนอกของ Arduino Due เพื่อส่งผ่านค่าความถี่ไปยัง Arduino Due นอกจากการควบคุมความถี่แล้ว Arduino Uno ยังควบคุมแอมพลิจูด (ผ่านเครื่องวัดศักย์ไฟฟ้าแบบดิจิตอล + OpAmp) เช่นเดียวกับ I/O--- จะมีพื้นที่ให้เล่นอีกมาก

ขั้นตอนที่ 1: สร้าง Sine Data Array

เนื่องจากการคำนวณแบบเรียลไทม์ต้องใช้ CPU จึงจำเป็นต้องมีอาร์เรย์ข้อมูลไซน์เพื่อประสิทธิภาพที่ดีขึ้น

uint32_t sin768 PROGMEM= ….ในขณะที่ x=[0:5375]; y = 127+127*(sin(2*pi/5376/*หรือ # ที่คุณต้องการขึ้นอยู่กับข้อกำหนด*/))

ขั้นตอนที่ 2: เปิดใช้งาน Parallel Output

ต่างจาก Uno เนื่องจาก Due มีการอ้างอิงที่จำกัด อย่างไรก็ตาม ในการสร้างคลื่นไซน์ 3 เฟสโดยอิงจาก Arduino Uno ประการแรกประสิทธิภาพไม่เป็นที่ยอมรับเนื่องจาก MCLK ต่ำ (16MHz ในขณะที่ Due คือ 84MHz) ประการที่สอง GPIO ที่ จำกัด สามารถผลิตเอาต์พุตสูงสุด 2 เฟสและคุณต้องการเพิ่มเติม วงจรอนาล็อกเพื่อผลิตเฟสที่ 3 (C=-AB)

การติดตามการเปิดใช้งาน GPIO ส่วนใหญ่ขึ้นอยู่กับการลองและทดลองใช้งาน + แผ่นข้อมูลที่ไม่เป็นประโยชน์ของ SAM3X

PIOC->PIO_PER = 0xFFFFFFFE; //ตัวควบคุม PIO PIO เปิดใช้งานการลงทะเบียน (อ้างอิง p656 ของแผ่นข้อมูล ATMEL SAM3X) และ https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 และ 44-51 ถูกเปิดใช้งาน

PIOC->PIO_OER = 0xFFFFFFFE; //เอาต์พุตคอนโทรลเลอร์ PIO เปิดใช้งานการลงทะเบียน อ้างถึง p657 ของแผ่นข้อมูล ATMEL SAM3X PIOC->PIO_OSR = 0xFFFFFFFE; // การลงทะเบียนสถานะเอาต์พุตคอนโทรลเลอร์ PIO อ้างถึง p658 ของแผ่นข้อมูล ATMEL SAM3X

PIOC->PIO_OWER = 0xFFFFFFFE; //เอาต์พุต PIO เปิดใช้งานการลงทะเบียน อ้างถึง p670 ของแผ่นข้อมูล ATMEL SAM3X

//PIOA->PIO_PDR = 0x30000000; // ตัวเลือกประกัน ดูเหมือนจะไม่ส่งผลต่อประสิทธิภาพการทำงาน พินดิจิตอล 10 เชื่อมต่อกับทั้ง PC29 และ PA28 พินดิจิตอล 4 เชื่อมต่อกับทั้ง PC29 และ PA28 ที่นี่เพื่อปิดการใช้งาน PIOA #28 & 29

ขั้นตอนที่ 3: เปิดใช้งาน Interrupt

เพื่อเพิ่มประสิทธิภาพสูงสุด โหลด CPU ควรต่ำที่สุด อย่างไรก็ตามเนื่องจากการติดต่อกันที่ไม่ใช่ 1 ต่อ 1 ระหว่างพินของ CPU และ Due pin จำเป็นต้องมีการดำเนินการบิต

คุณสามารถเพิ่มประสิทธิภาพอัลกอริทึมเพิ่มเติมได้ แต่ห้องมีจำกัดมาก

ถือเป็นโมฆะ TC7_Handler(โมฆะ){ TC_GetStatus(TC2, 1);

t = t%ตัวอย่าง; // ใช้ t%samples แทน 'if' เพื่อหลีกเลี่ยง t. ล้น

phaseAInc = (ที่ตั้งไว้ล่วงหน้า*t)%5376; //ใช้ %5376 เพื่อหลีกเลี่ยงดัชนีอาร์เรย์ล้น

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768[phaseAnc]<<1; // อ้างถึง PIOC: PC1 ถึง PC8, Arduino Due pin ที่สอดคล้องกัน: พิน 33-40 ดังนั้นให้เลื่อนไปทางซ้าย 1 หลัก

p_B = sin768[phaseBInc]<<12; // อ้างถึง PIOC: PC12 ถึง PC19, Arduino Due pin ที่สอดคล้องกัน: พิน 51-44 ดังนั้นให้เลื่อนไปทางซ้าย 12 หลัก

p_C = sin768[phaseCInc]; // เฟส C ที่ใช้เอาต์พุต PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 และ PC29, Arduino Due pin ที่สอดคล้องกัน: พินดิจิตอล: 9, 8, 7, 6, 5, 4, 3, 10 ตามลำดับ

p_C2 = (p_C&B11000000)<<22; // สิ่งนี้สร้าง PC28 และ PC29

p_C3 = (p_C&B00111111)<<21; // สิ่งนี้สร้าง PC21-PC26

p_C = p_C2|p_C3; // สิ่งนี้สร้างเอาต์พุตคู่ขนานของเฟส C

p_A = p_A|p_B|p_C; // เอาต์พุต 32 บิต = เฟส A (8 บิต) | เฟส B | เฟส C

PIOC->PIO_ODSR = p_A; //เอาต์พุตลงทะเบียน =p_A

t++; }

ขั้นตอนที่ 4: R/2R DAC

สร้าง 3x8bit R/2R DAC, อ้างอิงมากมายบน Google

ขั้นตอนที่ 5: รหัสเต็ม

#define _BV(x) (1<<(x)); uint32_t sin768 PROGMEM= /* x=[0:5375]; y = 127+127*(บาป(2*พาย/5376)) */

uint32_t p_A, p_B, p_C, p_C2, p_C3; // เฟส A ค่าเฟส B เฟส C - แม้ว่าเอาต์พุตจะเป็น 8 บิตเท่านั้น แต่ค่า p_A และ p_B จะถูกดำเนินการเพื่อสร้างค่า 32 บิตใหม่เพื่อจัดการกับเอาต์พุต PIOC 32 บิต

uint16_t phaseAInc, phaseBInc, phaseCInc, ความถี่, freqNew; ช่วงเวลา uint32_t; ตัวอย่าง uint16_t ที่ตั้งไว้ล่วงหน้า; uint32_t เสื้อ = 0;

การตั้งค่าเป็นโมฆะ () {

// การตั้งค่า PIOC เอาต์พุตแบบขนาน: Arduino Due pin33-40 ใช้เป็นเอาต์พุตเฟส A ในขณะที่พิน 44-51 ทำงานสำหรับเอาต์พุตเฟส B

PIOC->PIO_PER = 0xFFFFFFFE; //ตัวควบคุม PIO PIO เปิดใช้งานการลงทะเบียน (อ้างอิง p656 ของแผ่นข้อมูล ATMEL SAM3X) และ https://arduino.cc/en/Hacking/PinMappingSAM3X, Arduino Due pin 33-41 และ 44-51 ถูกเปิดใช้งาน

PIOC->PIO_OER = 0xFFFFFFFE; //เอาต์พุตคอนโทรลเลอร์ PIO เปิดใช้งานการลงทะเบียน อ้างถึง p657 ของแผ่นข้อมูล ATMEL SAM3X

PIOC->PIO_OSR = 0xFFFFFFFE; // การลงทะเบียนสถานะเอาต์พุตคอนโทรลเลอร์ PIO อ้างถึง p658 ของแผ่นข้อมูล ATMEL SAM3X

PIOC->PIO_OWER = 0xFFFFFFFE; //เอาต์พุต PIO เปิดใช้งานการลงทะเบียน อ้างถึง p670 ของแผ่นข้อมูล ATMEL SAM3X

//PIOA->PIO_PDR = 0x30000000; // ตัวเลือกประกัน, ดูเหมือนไม่มีผลกับประสิทธิภาพ, พินดิจิตอล 10 เชื่อมต่อกับทั้ง PC29 และ PA28, พินดิจิตอล 4 เชื่อมต่อกับทั้ง PC29 และ PA28, ที่นี่เพื่อปิดการใช้งานปิดการใช้งาน PIOA #28 & 29 // การตั้งค่าตัวจับเวลา, อ้างถึง https://arduino.cc/en/Hacking/PinMappingSAM3X, pmc_set_writeprotect (เท็จ); // ปิดใช้งานการป้องกันการเขียนของการลงทะเบียนการควบคุมการจัดการพลังงาน

pmc_enable_periph_clk(ID_TC7); // เปิดใช้งานตัวนับเวลานาฬิกาต่อพ่วง7

TC_Configure(/* นาฬิกา */TC2, /* ช่อง */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1); //TC clock 42MHz (นาฬิกา, ช่อง, เปรียบเทียบการตั้งค่าโหมด) TC_SetRC(TC2, 1, ช่วงเวลา); TC_Start(TC2, 1);

// เปิดใช้งานการขัดจังหวะตัวจับเวลาบนตัวจับเวลา TC2->TC_CHANNEL[1]. TC_IER=TC_IER_CPCS; // IER = ขัดจังหวะ เปิดใช้งานการลงทะเบียน TC2->TC_CHANNEL[1]. TC_IDR=~TC_IER_CPCS; // IDR = ขัดจังหวะปิดการใช้งานการลงทะเบียน

NVIC_EnableIRQ(TC7_IRQn); // เปิดใช้งานการขัดจังหวะในความถี่ตัวควบคุมการขัดจังหวะเวกเตอร์ที่ซ้อนกัน = 60; // เริ่มต้นความถี่เป็น 60Hz ที่ตั้งไว้ล่วงหน้า = 21; // ดัชนีอาร์เรย์เพิ่มขึ้น 21 ตัวอย่าง = 256; //เอาต์พุตตัวอย่าง 256/ช่วงรอบ = 42000000/(ความถี่*ตัวอย่าง); //การขัดจังหวะนับ TC_SetRC(TC2, 1, ช่วง); //เริ่ม TC Serial.begin(9600); //เพื่อจุดประสงค์ในการทดสอบ }

เป็นโมฆะ checkFreq()

{ freqNew = 20000;

ถ้า (freq == freqNew) {} else

{ ความถี่ = ความถี่ใหม่;

ถ้า (ความถี่>20000) {ความถี่ = 20000; /*ความถี่สูงสุด 20kHz*/};

ถ้า (ความถี่<1) {ความถี่ = 1; /*ความถี่ต่ำสุด 1Hz*/};

if (freq>999) {preset = 384; ตัวอย่าง = 14;} //สำหรับความถี่ >=1kHz, 14 ตัวอย่างสำหรับแต่ละรอบ

else if (freq>499) {preset = 84; ตัวอย่าง = 64;} // สำหรับ 500<=frequency99) {preset = 42; ตัวอย่าง = 128;} //สำหรับ 100Hz<=ความถี่<500Hz, 128 ตัวอย่าง/รอบ

อื่น ๆ {preset = 21; ตัวอย่าง = 256;}; //สำหรับความถี่<100hz, 256 ตัวอย่างสำหรับแต่ละรอบ

ช่วงเวลา = 42000000/(ความถี่*ตัวอย่าง); เสื้อ = 0; TC_SetRC(TC2, 1, ช่วง); } }

วงเป็นโมฆะ () {

ตรวจสอบความถี่ (); ล่าช้า (100); }

เป็นโมฆะ TC7_Handler (เป็นโมฆะ)

{ TC_GetStatus(TC2, 1);

t = t%ตัวอย่าง; // ใช้ตัวอย่าง t% เพื่อหลีกเลี่ยงการล้นของ t phaseAInc = (preset*t)%5376; //ใช้ %5376 เพื่อหลีกเลี่ยงดัชนีอาร์เรย์ล้น

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768[phaseAnc]<<1; // อ้างถึง PIOC: PC1 ถึง PC8, Arduino Due pin ที่สอดคล้องกัน: พิน 33-40 ดังนั้นให้เลื่อนไปทางซ้าย 1 หลัก

p_B = sin768[phaseBInc]<<12; // อ้างถึง PIOC: PC12 ถึง PC19, Arduino Due pin ที่สอดคล้องกัน: พิน 51-44 ดังนั้นให้เลื่อนไปทางซ้าย 12 หลัก

p_C = sin768[phaseCInc]; // เฟส C ที่ใช้เอาต์พุต PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 และ PC29, Arduino Due pin ที่สอดคล้องกัน: พินดิจิตอล: 9, 8, 7, 6, 5, 4, 3, 10 ตามลำดับ

p_C2 = (p_C&B11000000)<<22; // สิ่งนี้สร้าง PC28 และ PC29

p_C3 = (p_C&B00111111)<<21; //สิ่งนี้สร้าง PC21-PC26 //Serial.println(p_C3, BIN); p_C = p_C2|p_C3; // สิ่งนี้สร้างเอาต์พุตคู่ขนานของเฟส C

p_A = p_A|p_B|p_C; //เอาต์พุต 32 บิต = เฟส A (8 บิต)|เฟส B|เฟส C //Serial.println(p_A>>21, BIN); //PIOC->PIO_ODSR = 0x37E00000;

PIOC->PIO_ODSR = p_A; //เอาต์พุตลงทะเบียน =p_A t++; }

แนะนำ: