G'aroyib natija pulslarni hisoblashga harakat qilmoqda

Men umidsizlikka tushib qolganman va yordamga muhtojman.

Men avtomatlashtirilgan rasadxona qurmoqdaman va hozirda observatoriya qubba aylanishini boshqarishga urinib ko'rmoqdaman. Gumbaz qadamli vosita yordamida aylanadi va u yaxshi ishlaydi. Gumbazning aylanishi shuningdek, gumbaz harakat qilayotganligini mustaqil tekshirish uchun aylanuvchi kodlovchi ham aylanadi. Garchi RE kvadratura turiga kirsa-da, men faqat ikkita kanaldan RE konteynerlarini hisoblayman, chunki men yo'nalish ma'lumotlariga muhtoj emasmiz.

Endi nima qilmoqchiman, har bir RE retseptorining jufti o'rtasida qancha dvigatelning harakatlanish pulsi borligini hisoblash. Buning sababi gumbaz harakatlarini kuzatish va murosasizlikni aniqlashdir. Haqiqiy vosita pulslari barcha gumbaz pozitsiyasini hisoblash uchun ishlatiladi.

Bunga erishish uchun men ULN2803A inverting buffer va Arduino Nano bilan kichik taxtali qurdim. Nano kompaniyasida PIN kontekstini hisoblash uchun PIN o'zgarishidagi keskinliklar D11 va D12 pinlerinde qo'llaniladi. Pin D7, shuningdek, hozirgi vaqtda mavjud bo'lmasa ham, Home Position sensorini kuzatish uchun ishlatiladi. Motor pulslari bufer orqali D2 (INT0) ga yuboriladi va dvigatel yo'nalishi D3 (INT1) pinini chiqarish uchun tampon orqali yuboriladi. Keyinchalik, vosita yo'nalishiga qarab, yuqoriga yoki pastga, qidiruv pulslarini hisoblash uchun tashqi tugmalar qo'llaniladi.

Ma'lumot uchun, Velleman VM110 USB sxemasi mavjud bo'lib, u shuningdek, qaytib kodlovchi shomilni oladi. Bu menga qaytib kodlovchi milni qo'l bilan aylantirganda, mening taxtga xuddi shunday javob berishini tekshirishning oddiy usulini beradi.

OK - afsuski, bu shunchaki uzun shamollangan, lekin hozir g'alati.

Vositachiliksiz REni aylantirganda hamma narsa yaxshi. Velleman taxtasi kabi to'rt marta ko'proq impulslarni olaman, chunki men PIN o'zgarishlarini ishlatib, har bir ko'tarilish va tushishni tetikleyen, enkoderning to'liq aylanishiga emas. Bu taxmin qilinganidek sodir bo'ladi va hamma narsa yaxshi va barqaror.

BUT - men vositani ishga tushirganimda, enkoderni har safar ko'chirganimda, yuzlab RE tuxumlarini olaman va ba'zan enkoderga tegmasdan RE retseptorlari ortib boradi.

Aniq javob - bu RFI ning bir shakli, ammo men uni yo'q qilish uchun qo'lidan kelgan barcha ishlarni qildim. Motor drayveri va nanoSIM kartasi himoyalanmagan muhofazada bo'lganligi sababli, vosita kabeli ekranlangan kabeli va to'rt dvigatelning har birida 10uH choklar mavjud. Nihoyat, har qanday RFI kuchlanish liniyalaridan pastga tushirilishini kamaytirish uchun vosita qutisiga kelgan quvvat manbaiga filtr qo'ydim.

ULN2803A buferidan foydalanish bu ishni bajarish uchun mening so'nggi urinishim edi. Ilgari signallar to'g'ridan-to'g'ri nanoSIM pinlarga o'tdi. Tampon bilan kirish qismida 20 kata pull-up va chiqishlarda 10 kata pull-updan foydalanganman. Bu Velleman kartochkasi kirish devorining bevosita nusxasi bo'lib, men muammosiz ishlashni bilardim.

Men kirish pinidagi mexanik impulslarga o'zimdagi Nano-ga qaradim va ularda 70 sS davomiyligi va 497 Gts chastotasi yoqimli, o'tkir qirrali pulslar bor. Nozo'ravonlik tezligini Accelstepper kutubxonasidan foydalanib 500 Gts ga sozlang.

Endi bu dasturiy ta'minot muammosi ekanligiga shubha qilaman. Bu meni hayratlantirmaydi, chunki men bularning barchasi uchun juda yangi, faqat kerakli narsani qilish uchun har bir bosqichda etarlicha o'rganishga harakat qilaman. Kodni biriktirdim - bu mening muammolarimga aloqador bo'lmagan juda ko'p I2C narsalarsiz yo'qolgan versiyasi.

Yana ma'lumot uchun. attachInterrupt() funktsiyasidan foydalangan holda va to'g'ridan-to'g'ri ro'yxatdan o'tishni o'rnatdim - farq yo'q!

Yaxshiyamki, haqiqatan ham, kimdir menga yordam berishim mumkinligini umid qilaman.

Hurmat bilan, Hugh

/*          
ABoard3  
ROTATION MONITORING AND POSITION
Version AB3_stripped
*****************************PURPOSE*****************************************
This sketch is used on an Arduino Nano to count the motor pulses from ABoard1
and the Rotary Encoder ticks. The motor pulse count between encoder ticks is
used to detect dome jamming.
****************************INPUTS*******************************************
PIN CHANGE INTERRUPTS
**********ROTARY ENCODER INPUT*********
The rotary encoder is a Bourns ENA1J-B28 L00064L 1139M MEX 64 cycle per turn
optical encoder. This is connected to ABoard3 Pins D11 and D12. These pins
connect to Channel A and Channel B respectively. Pin change interrupts are used
to receive the rotary encoder output.
(The output pulses from the rotary encoder is also sent to the Velleman board
for use by LesveDomeNet for finding dome position)
*********HOME POSITION INPUT*********
The home position sensor is an Omron EESX671 Optical Sensor.
The sensor output is connected to ABoard3 Pin D7.
Pin change interrupt PCINT21 records activation/deactivation of the sensor.
EXTERNAL INTERRUPTS
*********MOTOR PULSE INPUT***********
The pulses sent to the G251X stepper driver are also sent to Aboard3 Pin D2.
This pin is the External Interrupt pin, vector INT0
*********MOTOR DIRECTION INPUT********
Motor direction is input to ABoard3 from ABoard2. ABoard2 pin, pnVmInRotMotor
(AB2:A0{54}) is connected to Velleman pins DI4 and DO2 and also to AB3:D3.
AB3:D3 is an External Interrupt pin, vector INT1.
*/

#include                        
#include "streaming.h"                        
#include "I2C_AnythingHEG.h"   
#include                     

//CONSTANTS                       
//PIN ASSIGNMENTS For ABOARD3
const uint8_t pnMotorPulse = 2;      //Port PD2, INT0, ISR(INT0_vect){}
const uint8_t pnMotorDirection = 3;  //Port PD3, INT1, ISR(INT1_vect){}
const uint8_t pnDomeAtHome = 7;      //Port PD7, PCINT23,ISR(PCINT2_vect){}
const uint8_t pnREChanA = 11;        //Port PB3, PCINT3, ISR(PCINT0_vect){}
const uint8_t pnREChanB = 12;        //Port PB4, PCINT4, ISR(PCINT0_vect){}

//*****************EXPERIMENTAL STUFF FOR PULSE COUNTING*******************************                  
uint16_t volatile myTest = 0;
int32_t volatile ratioCount = 0L;
int32_t volatile totalCount = 0L;
int32_t volatile tickCount = 0L;
uint8_t volatile halftickCount = 0;
int32_t volatile addPulse = 0L; 

void setup() {
  //**********************************SERIAL FOR DEBUG ONLY************************
  Serial.begin(115200);
  //*************************INPUT PIN MODE SETUP**********************************
  //NOTE Set all UNUSED PCINT0:5 pins (D8, D9, D10, D11) to OUTPUT.
  //and set the value to LOW
  //The actual pins used to receive interrupts have external 10k pull-ups.
  //This is to reduce susceptibility to interference causing false triggering.
  pinMode(pnMotorPulse, INPUT); //D2
  pinMode(pnMotorDirection, INPUT); //D3
  pinMode(pnDomeAtHome, INPUT); //D7
  pinMode(pnREChanA, INPUT); //D11
  pinMode(pnREChanB, INPUT); //D12
  pinMode(4, OUTPUT); //D4
  digitalWrite(4, LOW);
  pinMode(8, OUTPUT); //D8
  digitalWrite(8, LOW);
  pinMode(9, OUTPUT); //D9
  digitalWrite(9, LOW);
  pinMode(10, OUTPUT); //D10
  digitalWrite(10, LOW);
  //******************SET UP AddPulse According to Motor Direction******************
  //This is needed to make sure the pulse counting starts in the correct direction
  //as the direction is only checked in the ISR after a change has occurred.
  //If Motor Direction is AntiClockwise, change to Subtract a pulse
  if( digitalRead(pnMotorDirection)) {
    addPulse = 1L;
  } else {
    addPulse = -1L;
  }
  //**************************SET UP PIN CHANGE INTERRUPTS**************************
  //Set the Pin Change Interrupt Masks
  //Clear all bits to start with
  PCMSK0 &= 0b00000000; //Clear all bits
  PCMSK1 &= 0b00000000; //Clear all bits
  PCMSK2 &= 0b00000000; //Clear all bits
  //Mask for PCINTs 0 through 7 is PCMSK0 (Rotary Encoder Pulses)
  //Need to allow interrupts on PCINT3 and PCINT4, so set bits 3 and 4
  //PCINT3 is Nano  pin D11 and PCINT4 is Nano pin D12
  //Use a compound bitwise OR to set the bits
  PCMSK0 |= 0b00011000; //Enable PCINT3 ONLY (bit 3)
  //Interrupt on pins 11 and 12, RE Ticks
  //Mask for PCINTs 16through 23 is PCMSK2 (Home Position)
  //Need to allow interrupts on PCINT23 so set bit 7
  PCMSK2 |= 0b10000000; //Interrupt on pin 7, Home Position Sensor activated
  //Now enable the interrupts (TURN THEM ON) by setting bits in PCICR
  //PCICR is Pin Change Interupt Control Register.Set bit 0 (PCIE0)  
  //to enable interrupts PCINT0:7 This catches PCINT3 and 4 - RE Ticks
  //Set bit 2 (PCIE2) to enable interrupts PCINT16:23. Catches PCINT21 - Home Position Sensor
  PCICR &= 0b00000000; //Clear PCICR register 
  PCICR |= 0b00000001; //Set bit 0 - Catches PCINT3 & PCINT4 - RE Ticks
  PCICR |= 0b00000100; //Set bit 2 - Catch PCINT21 - Home Position Sensor
  //**************************SET UP 'EXTERNAL INTERRUPTS'**************************
  //Interupts on External Interrupt Pins D2 (INT0) and D3 (INT1).
  //INT0 (Nano pin D2)occurs when a stepper motor driver pulse is received
  //INT1 (Nano pin D3)occurs when the ABoard2 pin, pnVmInRotMotor toggles 
  //indicating a motor direction change.
  //To use the 'External Interrupts' the following registers need to be set-up:         
  //EICRA External Interrupt Control Register A       
  //Need to set Interrupt Sense Control bits ISC11 .. ISC00 (bits 3:0 in EICRA)
  //ISC01     ISC00 (INT0)    Interrupt
  //ISC11     ISC01 (INT1)    Generated by
 // 0         0             Low level on Pin
 // 0         1             Any Logical Change
 // 1         0             Falling Edge
 // 1         1             Rising Edge
  //First clear all bits, then set as follows:  
  //For INT1 - Motor Direction - Generate on ANY LOGICAL CHANGE     
  //bit 3 ISC11 0     
  //bit 2 ISC10 1 This combination = Any logical change causes interrupt 
  //For INT0 - Stepper Motor Pulses  - Generate on RISING EDGE      
  //bit 1 ISC01 1     
  //bit 0 ISC00 1 This combination = Rising edge of pulse causes interrupt
  //NOTE: To provide some immunity to RFI, Aboard3:Pins 2 & 3 are pulled high
  //using 10k resistors. 
  //So, code is
  EICRA &= 0b00000000; //Clear EICRA register
  EICRA |= 0b00000111;//Set bits 0,1 and 2 in EICRA register
  //EIMSK External Interrupt Mask Register        
  //Need to set External Interrupt Request Enables INT1 & INT0  (bits 1:0)          
  //First clear both bits, then set as follows: 
  //bit 1  INT1  1 External interrupt pin (D3) enabled   
  //bit 0  INT0  1 External interrupt pin (D2) enabled   
  //So, code is
  EIMSK &= 0b00000000; //Clear EIMSK register
  EIMSK |= 0b00000011;//Set bits 0 and 1 in EIMSK register
  //NOTE: Setting EIMSK TURNS ON THE EXTERNAL INTERRUPTS
  //************VARIABLE INITIALISATION*********
  myCommand = 0;
  myTest = 0;
  tickCount = 0L;
  totalCount = 0L;
} //END of setup

void loop() {
  //******************************COMMAND ACTIONS******************************
  if (myTest == 3) (
    //RE tick
    Serial << "Tick Count = " << tickCount << "  totalCount = " << totalCount << "\n";
    myTest = 0;
  }
}
//*************************FUNCTIONS/ISRs FROM HEREON*************************
ISR(INT0_vect) {
  //Triggered by stepper motor drive pulse from ABoard1
  totalCount = totalCount + addPulse;
}
ISR(INT1_vect) {
  //Triggered by a change in motor direction
  if(digitalRead(pnMotorDirection)) {
    addPulse = 1L;
  } else {
    addPulse = -1L;
  }
}
ISR(PCINT0_vect) {
  //Triggered by a ROTARY ENCODER TICK
  halftickCount++;
  if (halftickCount == 2) {
    //Make count same as Velleman
    tickCount++;
    halftickCount = 0;
    myTest = 3;
  }
}
ISR(PCINT2_vect) {
  //Triggered by activation of Home Position Sensor
  myTest = 4;
}
0
1) Sizning ko'lamga ega bo'lganingiz uchun siz uni mexanik impulslarga qarash uchun ishlatgansiz. Kodlovchi pulslarni ham ko'rib qoldingizmi? Ular qanday ko'rinishda? 2) Quadrature kodlovchisida men ko'pincha bitta kanalning har qanday vaqtda "tezkor" bo'lishini kutardim. Keyinchalik kodlayıcıni odatiy tarzda ishlatsangiz, siz +1, -1, +1, -1 qatorlarini nolga qo'shib olishingiz kerak. 3) AVR I/U registrlarini o'rnatish uchun standart dyuym PCMSK0 = _BV (PCINT3) | _BV (PCINT4); PCMSK0 & = 0b00000000 dan aniqroq ko'rinadigan ; PCMSK0 | = 0b00011000; , hech bo'lmaganda AVR dasturlash bilan tanish bo'lganlarga.
qo'shib qo'ydi muallif Sprogz, manba
PCMSK0 & = 0b00000000;//barcha bitlarni tozalash - PCMSK0 = 0; juda aniqroq emasmi? Men Gerbenning javobiga qo'shilaman. Bezovta qilingan ko'p baytli o'zgaruvchiga kirishni "himoya qilish" ni harakat qilib ko'ring. To'xtatishlar bo'limiga qarang.
qo'shib qo'ydi muallif Nick Gammon, manba
Quadrature enkoder chiqishi va Arduino o'rtasida to'g'ri birgalikda zaminingiz bormi? Agar shunday bo'lsa, @EdgarBonet to'g'ri. Quadrature kodlovchilari aqldan ozish mumkin, shuning uchun siz kodlovchini to'g'ri o'qishingiz, qadam yo'nalishini va har bir o'qishda aniqlik kiritishingiz kerak bo'ladi. Shunday qilib, agar u +1 va undan keyin 1-qatorni yoki boshqa ketma-ketlikni 100 marta ketma-ket zabt etsa, siz yangi joyning nima ekanligini bilib olasiz va shuning uchun siz ham buni rad qildingiz. Har bir kvadratura chiqishi uchun 2.2uF qopqoqni ham qo'shishga harakat qilib ko'ring.
qo'shib qo'ydi muallif meepsh, manba
Kodlovchini to'g'ri o'qish - bu sizga kerakli bo'lgan dasturiy ta'minot.
qo'shib qo'ydi muallif meepsh, manba
Qaytgan enkoder elektr yoki optikmi? Men sizdan so'rashni so'rayman, agar siz kalitni zabt etish yoki ehtimol optik qabul qilgich bilan chegarada ochilsa yoki o'chirib qo'yish bilan bog'liq muammolaringiz bo'lsa. Agar shunday bo'lsa, uni hal etishga yordam beradigan usullardan biri to'rtta kodlangan pulslarni to'g'ri hal qilishdir. Ushbu blog postasi to'rtta kodlangan pulslarni kod hal qilishning ishonchli usulini ko'rsatadi: thewanderingengineer.com/2014/08/11/… Regadlar,
qo'shib qo'ydi muallif CMaster, manba
Protsessorda da'vo qilishning muqobilligi bu maqsadga mo'ljallangan chipdan foydalanishdir. Bu mos keladigan narsa: elmelectronics.com/ic/elm402 Regards,
qo'shib qo'ydi muallif CMaster, manba

1 javoblar

Ba'zi o'zgaruvchilar uchun int32_t foydalanishga hojat yo'q. 8-bitli protsessorda 8 bitdan ortiq bo'lgan parametrlarni ishlatish bilan bog'liq muammo, protsessor qiymatini olish uchun 4 ta o'qishga muhtoj. Ularning o'rtalarida interruptlar paydo bo'lishi mumkin, natijada eski qiymatning ba'zi bitlari va yangi bitlarning bir qismi mavjud.

Ba'zi bir o'zgaruvchiga faqat 8 bit kerak.

uint8_t volatile myTest = 0;
int32_t volatile totalCount = 0L;
int32_t volatile tickCount = 0L;
uint8_t volatile halftickCount = 0;
int8_t volatile addPulse = 0L; 

Keyingi narsa, atomning qiymatini o'qishdir.

void loop()                                             
{                                               
//******************************COMMAND ACTIONS******************************  

if (myTest == 3)   //RE tick
{
    noInterrupts();
    int32_t tickCountCopy = tickCount;
    int32_t totalCountCopy = totalCount;
    interrupts();
    Serial << "Tick Count = " << tickCountCopy << "  totalCount = " << totalCountCopy << "\n"; 
    myTest = 0; 
}
}   

PS. bu mutlaqo javob emas, lekin bu sharhga mos kelmadi.

1
qo'shib qo'ydi
Bu yerda haqiqiy zo'riqish yo'q, lekin, ehtimol siz kutganingizdek, aniq bir o'tish emas. Mening taxminimcha shmitt trigger faqat ishlaydi. Mening javobim muammoni hal qilmasa ham, siz hali ham kodingiz bilan hisoblashingiz mumkin bo'lgan muammoni ko'rsatib turibdi.
qo'shib qo'ydi muallif Al., manba
Salom, va Gerben va Nickga rahmat. Tavsiya qilingan o'zgarishlarni amalga oshirdim, lekin ular aslida yomon ishlarni qilishni tuyuldi, shuning uchun ham yaxshi emas edi, chunki hatto qadamli vosita qilmasdan RE kanallarining har birida bir nechta tetiklashuvni boshladim.
qo'shib qo'ydi muallif SeaDrive, manba
Oops - yangi satrni ko'rishni xohladim, lekin tugashdan oldin bu sharhni yuborganman. Shunday qilib, endi formatlashning etishmasligi uzr. Men Rotary Encoderni chaqirishim kerak degan xulosaga keldim. Men buni tasavvur qilishni talab qilmaslik uchun optik kodlovchi deb hisoblaganman, lekin hozir men taxminlar noto'g'ri deb o'ylayman. Men RC-ni ishlatib, kichkinagina qo'shimcha qurilmani yaratmoqchiman. Umid qilamanki hat bu muammoni hal qila oladi. Yaxshi xabar shundaki, haqiqiy qadam pulslari hech qanday muammosiz hisoblanmoqda. Rahmat, Hugh.
qo'shib qo'ydi muallif SeaDrive, manba
Salom, enkoder chiqindilariga qarash uchun qamrovimdan foydalanishga harakat qildim, lekin uni qanday qilib to'g'ri ishlatishni bilmayman va mazmunli natijalarga erisha olmadim. Men har bir enkoder kanalida taxminan 5 mS kechikishdan foydalangan holda nashr etuvchi kartasini yaratdim va nihoyat, u barcha kerakli ishlarni bajaradi. Dekabr oyi boshida bu muammoni hal qildim, shuning uchun uni hal qilish uchun bu vaqtni oldi. Aslida bu muammoni hal qilish uchun ko'makimni sotib oldim. Yana javob bergan va izoh bergan har bir odamga rahmat. Hughni hurmat qilaman
qo'shib qo'ydi muallif SeaDrive, manba
@HuGGillhespie, agar muammo hozir hal etilsa, iltimos, o'zingizning savolingizga javob yozib, uni echilgan deb belgilang.
qo'shib qo'ydi muallif meepsh, manba