מחולל גל סיני 3 פאזי מבוסס על Arduino Due: 5 שלבים
מחולל גל סיני 3 פאזי מבוסס על Arduino Due: 5 שלבים
Anonim
מחולל גל סיני 3 פאזי מבוסס על Arduino Due
מחולל גל סיני 3 פאזי מבוסס על Arduino Due

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

פרויקט זה מסוגל לייצר עד 3 סיבים של גל סינוס @ 256 דגימות / מחזור בתדירות נמוכה (<1 קילוהרץ) ו -16 דגימות / מחזור @ תדירות גבוהה (עד 20 קילוהרץ), וזה מספיק טוב כדי להחליק אותו על ידי LPF פשוטים הפלט כמעט מושלם.

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

מאחר וקיבולת המעבד מירבית באמצעות הגישה המוצגת בקובץ המצורף, השתמשתי ביחידת בקרה של Arduino Uno, המנצלת את ההפרעה החיצונית של Arduino Due כדי להעביר את ערך התדר ל- Arduino Due. בנוסף לבקרת התדרים, ה- Arduino Uno שולט גם במשרעת (באמצעות מד פוטנציאל דיגיטלי + OpAmp) כמו גם I/O --- יהיה הרבה מקום לשחק איתו.

שלב 1: צור מערך נתונים סיני

מכיוון שחישוב בזמן אמת דורש מעבד, יש צורך במערך נתוני סינוס לביצועים טובים יותר

uint32_t sin768 PROGMEM =…. בעוד x = [0: 5375]; y = 127+127*(חטא (2*pi/5376/*או כמה # שאתה מעדיף תלוי בדרישה*/))

שלב 2: הפעלת פלט מקביל

בניגוד ל- Uno, ל- Due יש התייחסות מוגבלת. עם זאת, על מנת לייצר גל סינוס 3 פאזי המבוסס על Arduino Uno, הראשונה מכל, הביצועים אינם ניתנים לשבח בשל MCLK הנמוך שלו (16MHz בעוד Due הוא 84MHz), השני, הוא מוגבל ב- GPIO יכול לייצר פלט דו פאזי לכל היותר ואתה צריך עוד פלט מעגל אנלוגי לייצור השלב השלישי (C = -AB).

מעקב אחר הפעלת GPIO התבסס ברובו על ניסיון וניסוי+גיליון נתונים לא מועיל של SAM3X

PIOC-> PIO_PER = 0xFFFFFFFE; // בקר PIO בקר רישום הפעלה (עיין בעמ '656 של גליון הנתונים של ATMEL SAM3X) ו- https://arduino.cc/en/Hacking/PinMappingSAM3X, סיכת Arduino Due 33-41 ו- 44-51 הופעלו

PIOC-> PIO_OER = 0xFFFFFFFE; // פלט בקר פלט בקר PIO, עיין ב p657 של גליון הנתונים של ATMEL SAM3X PIOC-> PIO_OSR = 0xFFFFFFFE; // רשום סטטוס פלט בקר PIO, עיין בעמ '658 של גליון הנתונים של ATMEL SAM3X

PIOC-> PIO_OWER = 0xFFFFFFFE; // פלט כתיבה של פלט כתיבת פלט, עיין ב p670 של גליון הנתונים של ATMEL SAM3X

// PIOA-> PIO_PDR = 0x30000000; // אופציונלי כביטוח, לא נראה שישפיע על הביצועים, פין דיגיטלי 10 מתחבר הן ל- PC29 והן ל- PA28, פין דיגיטלי 4 מתחבר הן ל- PC29 והן ל- PA28, כאן כדי להשבית את השבתת ה- PIOA #28 & 29

שלב 3: הפעלת הפרעה

כדי למקסם את הביצועים שלו, עומס המעבד צריך להיות נמוך ככל האפשר. אולם בשל ההתכתבות שאינה 1to1 בין סיכת המעבד לסיכת Due, יש צורך בפעולת ביט.

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

void TC7_Handler (void) {TC_GetStatus (TC2, 1);

t = t%דוגמאות; // השתמש בדוגמאות t%במקום 'אם' כדי למנוע הצפה של t

phaseAInc = (מוגדר מראש*t)%5376; // השתמש ב- %5376 כדי להימנע מהצפת אינדקס מערכים

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // עיין ב- PIOC: PC1 ל- PC8, סיכת Arduino Due המתאימה: סיכה 33-40, מכאן משמרת שמאלה למשך ספרה אחת

p_B = sin768 [phaseBInc] << 12; // עיין ב- PIOC: PC12 ל- PC19, סיכת Arduino Due המתאימה: סיכה 51-44, ומכאן משמרת 12 ספרות שמאלה

p_C = sin768 [phaseCInc]; // פלט שלב C מעסיק PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 ו- PC29, פין Arduino Due המקביל: פין דיגיטלי: 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, המון ref ב- Google.

שלב 5: קוד מלא

#define _BV (x) (1 << (x)); uint32_t sin768 PROGMEM = /* x = [0: 5375]; y = 127+127*(sin (2*pi/5376))*/

uint32_t p_A, p_B, p_C, p_C2, p_C3; // שלב שלב B שלב C-למרות שהפלט הוא 8 סיביות בלבד, ערך p_A ו- p_B יופעל ליצירת ערך 32 סיביות חדש על מנת להתמודד עם פלט PIOC של 32 ביט.

uint16_t phaseAInc, phaseBInc, phaseCInc, freq, freqNew; מרווח uint32_t; uint16_t דוגמאות, מוגדרות מראש; uint32_t t = 0;

הגדרת בטל () {

// הגדרת PIOC פלט מקבילית: Arduino Due pin33-40 משמשים כפלט שלב A ואילו סיכה 44-51 עובדת עבור פלט שלב B

PIOC-> PIO_PER = 0xFFFFFFFE; // בקר PIO בקר רישום הפעלה (עיין בעמ '656 של גליון הנתונים של ATMEL SAM3X) ו- https://arduino.cc/en/Hacking/PinMappingSAM3X, סיכת Arduino Due 33-41 ו- 44-51 הופעלו

PIOC-> PIO_OER = 0xFFFFFFFE; // פלט בקר פלט של PIO, עיין ב p657 של גליון הנתונים של ATMEL SAM3X

PIOC-> PIO_OSR = 0xFFFFFFFE; // רשם סטטוס פלט בקר PIO, עיין בעמ '658 של גליון הנתונים של 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 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); // הפעל את ההפרעה בבקר הפרעות הווקטור המקוננות freq = 60; // לאתחל תדר כ- 60Hz מוגדר מראש = 21; // עלייה במדד המערך ב -21 דוגמאות = 256; // דגימות פלט 256/מרווח מחזור = 42000000/(freq*דוגמאות); // ספירות קטע TC_SetRC (TC2, 1, מרווח); // התחל TC Serial.begin (9600); // למטרת בדיקה}

check void check ()

{freqNew = 20000;

if (freq == freqNew) {} אחר

{freq = freqNew;

אם (תדירות> 20000) {freq = 20000; /*תדר מקסימלי 20kHz*/};

אם (freq <1) {freq = 1; /*תדר דקות 1Hz*/};

אם (תדירות> 999) {קבוע מראש = 384; דוגמאות = 14;} // לתדר> = 1kHz, 14 דוגמאות לכל מחזור

אחרת אם (freq> 499) {preset = 84; דוגמאות = 64;} // עבור 500 <= frequency99) {preset = 42; דוגמאות = 128;} // עבור 100Hz <= תדר <500Hz, 128 דוגמאות/מחזור

אחרת {קבוע מראש = 21; דוגמאות = 256;}; // לתדר <100 הרץ, 256 דוגמאות לכל מחזור

מרווח = 42000000/(freq*דוגמאות); t = 0; TC_SetRC (TC2, 1, מרווח); }}

לולאת חלל () {

checkFreq (); עיכוב (100); }

void TC7_Handler (void)

{TC_GetStatus (TC2, 1);

t = t%דוגמאות; // השתמשו בדוגמאות t%כדי להימנע מהצפה של t phaseAInc = (מוגדר מראש*t)%5376; // השתמש ב- %5376 כדי להימנע מהצפת אינדקס מערכים

phaseBInc = (phaseAInc+1792)%5376;

phaseCInc = (phaseAInc+3584)%5376;

p_A = sin768 [phaseAInc] << 1; // עיין ב- PIOC: PC1 ל- PC8, סיכת Arduino Due המתאימה: סיכה 33-40, מכאן משמרת שמאלה למשך ספרה אחת

p_B = sin768 [phaseBInc] << 12; // עיין ב- PIOC: PC12 ל- PC19, סיכת Arduino Due המתאימה: סיכה 51-44, ומכאן משמרת 12 ספרות שמאלה

p_C = sin768 [phaseCInc]; // פלט שלב C מעסיק PIOC: PC21, PC22, PC23, PC24, PC25, PC26, PC28 ו- PC29, פין Arduino Due המקביל: פין דיגיטלי: 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 ++; }

מוּמלָץ: