| Electronics > Projects, Designs, and Technical Stuff |
| Radio Direction Finding |
| << < (29/39) > >> |
| PA3BNX:
Hello Every Body, We are working on new Arduino Dopplers To see our progress look at this Dutch Forum http://www.zendamateur.com/viewtopic.php?f=11&t=7271&start=480 |
| PA3BNX:
Hello Every Body, I am trying to build a Arduino Uno R3 based Doppler that connects through USB to the PC and MyMapping.exe program. So see the shield and my initial improved sketch I updated the sketch and added a shield picture. ToDay 24-05-2015 Again updated the Sketch 01-05-2015 Fixed several issues Still working on the code --- Code: --- /* ((C))PA3BNX Trying to create a SuperSimpleArduinoDoppler on Arduino Uno R3 For this there is a special Arduino Com/USB input in MyMapping to show the headings on maps @12-04-2015 @13-04-2015 @15-04-2015 @17-04-2015 @22-04-2015 @24-04-2015 @25-04-2015 @26-04-2015 @27-04-2015 @29-04-2015 @01-05-2015 Not ready yet! Try max232 for Am WhatsonWatt DF to Need extra pin for that or use antPin ? Arrays are zero based !!!! Explaining Arduino pins. antPins[] Connect to antenna switcher pins refpa3bnx Connect to audio lowpass filter for soundcard referency input kPins[] Connect to kwadrant C's 4u7 kPins[12] Connect to discharge transistor //Not yet done in hardware kPinAnalogue Connect to sum point of 4 cap's */ //Byte= 0>255 //Int= -32768>32767 //String Serial params String inputString = ""; //Received serial string //Boolean boolean bStringComplete = false; //Complete '\n' rxed serial string boolean bNoSetKpins = false; //Do not change kPin[] because I am reading/empty them now boolean bMultiPathAverage = false; //Multipath heading found in received headings from Averaged //Const Integer //Must be modified to right pin number arduino and arduino shield harddware //Antenna Control Pins & refpa3bnx //Never use pins 0 and 1 because the UART must also function //So I started with pin 2 to byte antPin[4] = {2,3,4,5}; //Set antenna control pins (Not const because it can CCW/CW) byte max232Pin[2] = {7,8}; //Set Max232Pin vor AM plate antenna const byte refpa3bnx = 6; //Pin for Referency frequency output to soundcard //Kwadrant Capicity switches & analogue SCF read pin const byte kPin[5] = {9,10,11,12,13}; //4 pins caps 4u7 Last Pin in array = Discharge caps by bc547 const byte kPinAnalog = A0; //A0 read voltage across one 4u7 cap pin A0 to A5 const int cOffset = 511; // .5 * 1023 caps offset //Squelch Signals const byte cSqlclosed = 0; const byte cSqlclosed2open = 1; const byte cSqlopen2closed = 2; const byte cSqloverflow = 3; //Capicitors are full // //NoDegreesMaxMinValues const int cNodegrees = 999; //Squelch No Signal or cSqlopen2closed const int cMaxTime = 30; //15 Sec/cMainLoopDelay Max time const int cMainLoopDelay = 500; //How fast the main loop runs in mSec const int cMinAudioAmplitude = 100; //There is enough signal to SinCosDetect //Float const //const float pi = 4 * atan(1); //PI 3.14159 //const float rad = pi/180; const float rad1 = 180/PI; //57.295827 //const float TwoPi = 2 * pi; //TWO_PI //Integer //Array with the 4 kwandrant analogue cap tensions These can be -511 to +511 int Cap[4] = {0,0,0,0}; int Calibrate= 0; //degrees default byte sqlstatus = cSqlclosed; //------------ISR Main Interrupt //This runs always-------------------- ISR(TIMER0_COMPA_vect) { static byte c; //Do the Ant and Cap rotation here if (c==4){ c=0; } SetAntPins(c); SetMax232Pins(c); SetKpinsHigh; c++; } //---------Functions now------------------- //Max232Pins for AM Whatson Watt RDF void SetMax232Pins(byte t){ switch (t){ case 0: digitalWrite(max232Pin[0],HIGH); digitalWrite(max232Pin[1],LOW); break; case 1: digitalWrite(max232Pin[0],HIGH); digitalWrite(max232Pin[1],HIGH); break; case 2: digitalWrite(max232Pin[0],LOW); digitalWrite(max232Pin[1],LOW); break; case 3: digitalWrite(max232Pin[0],LOW); digitalWrite(max232Pin[1],HIGH); break; } } //Antenna Control Lines Just counts 1234 1234 etc void SetAntPins(byte t){ switch (t){ case 0: digitalWrite(antPin[0], HIGH); digitalWrite(antPin[3], LOW); digitalWrite(refpa3bnx,HIGH); break; case 1: digitalWrite(antPin[1], HIGH); digitalWrite(antPin[0], LOW); break; case 2: digitalWrite(antPin[2], HIGH); digitalWrite(antPin[1], LOW); digitalWrite(refpa3bnx,LOW); break; case 3: digitalWrite(antPin[3], HIGH); digitalWrite(antPin[2], LOW); break; } } //Set kwadrant Cap Pins just High void SetKpinsHigh(){ if (bNoSetKpins==false){ //Set all HIGH for (int i=0 ;i<4;i++){ digitalWrite(kPin[i],HIGH); } } } //Get the 4 analogue value's in Cap[] void GetCapValues(){ //All kwadrant Cap Pins HIGH for (byte i=0; i<4; i++) { digitalWrite(kPin[i],HIGH); } //Read them one by one digitalWrite(kPin[0],LOW); Cap[0] = analogRead(kPinAnalog)-cOffset; digitalWrite(kPin[0],HIGH); digitalWrite(kPin[1],LOW); Cap[1] = analogRead(kPinAnalog)-cOffset; digitalWrite(kPin[1],HIGH); digitalWrite(kPin[2],LOW); Cap[2] = analogRead(kPinAnalog)-cOffset; digitalWrite(kPin[2],HIGH); digitalWrite(kPin[3],LOW); Cap[3] = analogRead(kPinAnalog)-cOffset; digitalWrite(kPin[3],HIGH); } //Empty the 4 capicitors by discharging to 1/2 U void EmptyCaps(){ for (byte i=0; i<4; i++) { pinMode(kPin[i],LOW); } digitalWrite(kPin[5],HIGH); //Discharge cap pin bc547 delay(2100); //Let the 4 caps charge to 1/2 U to 99% 5 * (22k * (4,7uF * 4)) 2068 Sec digitalWrite(kPin[5],LOW); } //-------------Squelch----------------------- int Squelch(){ //Return the sqlstatus //Try Find a full cap int x; //Find cap with highest voltage/tension //Biggest value = cOffset (511) for(byte i=0; i<4; i++) { if abs((Cap[i]) >= cOffset ) { x = abs(Cap[i]); } } //See if there is a Full Cap //cOffset = Biggest value if (x >= cOffset) { return cSqloverflow; //Caps are full so need discharged } else if (x >= cMinAudioAmplitude) { return cSqlclosed2open; } else if (x < cMinAudioAmplitude) { return cSqlclosed; } } //Detect Multipath in SCF Caps boolean MultiPathDetectSCF(){ //Calc average of 4 kwadrants //If to large asymetric value return true //Can it do also the Quality 1-9 ? int x; for (int i=0 ; i<4 ; i++){ x += Cap[i]; } //150 of max 510 is the MultiPath level ? if (abs(x) > 150){ return true; } else { return false; } } //Calibrate int Cali(int degrees){ return LimitDegrees360(degrees(Calibrate + degrees)); } //Return Agrelo formatted string % and 3 digits always String Format3Degrees(int degrees){ String str; int digits[3]; int reminder; digits[0]=degrees/100; reminder = degrees % 100; digits[1]= reminder/10; reminder = reminder % 10; digits[2]=reminder; str += '%'; str += digits[0]; str += digits[1]; str += digits[2]; return str; } //Limit Degrees 0 to 360 degrees int LimitDegrees360(int d){ //Limit degrees 0 to 360 here if (d >= 360){ return d - 360; } else if (d < 360) { return d; } else if (d < 0) { return 360 + d; } else { return cNodegrees; } } //Average int Average(int d){ //If d = 999 (cNoDegrees) then reset average //Else return averaged degrees //Integer static int sum[4]; //Sum of counts for each kwadrant static int c[4]; //Cap tension/voltage in 4 kwadrant int xx[4] ={0,0,0,0}; //Adjacent kwadrants int z = 0; //Most adjacent headings int z1 = 0; //Other two kwandants headings int y = 0; //Index where the most headings are int avDegrees; //Averaged degrees //Limit amount off averaged headings if (c[0]+c[1]+c[2]+c[3] > cMaxTime ){ for (byte i=0; i<4 ; i++){ sum[i]=0; c[i]=0; return cNodegrees; } } if (d!=cNodegrees){ if (d >= 0 && d < 90){ sum[0] += d; c[0]++; } if (d >= 90 && d < 180){ sum[1] += d; c[1]++; } if (d >= 180 && d < 270){ sum[2] += d; c[2]++; } if (d >= 270 && d <= 360){ sum[3] += d; c[3]++; } } else { //Reset for (byte i=0; i<4; i++){ sum[i]=0; c[i]=0; bMultiPathAverage = false; } return cNodegrees; } //Find 2 adjacent kwadrants with hold most counts //Count all adjacents kwadrants xx[1] = c[0]+c[1]; xx[2] = c[1]+c[2]; xx[3] = c[2]+c[3]; xx[4] = c[3]+c[0]; //Find out in witch two kwadrants the most headings are for (byte i=0; i<4; i++){ if (xx[i] >= z){ z = xx[i]; //Most Headings y = i; //Witch 2 adjacent Array Index } } //Check for multipath switch(z){ case 0: z1 = 3; break; case 1: z1 = 4; break; case 2: z1 = 1; break; case 3: z1 = 2; break; } if (z > z1){ bMultiPathAverage = true; } else { bMultiPathAverage = false; } //Average the 2 most counts kwadrants switch(y){ case 1: avDegrees = (sum[0] + sum[1]) / c[y]; break; case 2: avDegrees = (sum[1] + sum[2]) / c[y]; break; case 3: avDegrees = (sum[2] + sum[3]) / c[y]; break; case 4: if (c[3] == 0 && c[0] > 0){ avDegrees = sum[0] / c[0]; break; } if (c[3] > 0 && c[0] == 0){ avDegrees = sum[3] / c[3]; break; } if (c[3] > 0 && c[0] > 0 ){ avDegrees = LimitDegrees360(((sum[3] / c[3]) + ((sum[0] / c[0]) + 360) / 2)); break; } } if (d == cNodegrees){ return avDegrees; } } //SinCosDetector Find the degrees from the 4 Cap[] tensions int SinCosDetector(){ int SinSum; int CosSum; int x; //In Cap[] is the tension value of 1 of the 4 C'S SinSum = Cap[0] - Cap[2]; CosSum = Cap[1] - Cap[3]; if (SinSum == 0 && CosSum == 0){ return cNodegrees; } else { return LimitDegrees360(atan2(SinSum,CosSum) * rad1); } } //=============SerialRx Event=========================== void serialEvent() { while (Serial.available()) { // get the new byte: char inChar = (char)Serial.read(); // add it to the inputString: inputString += inChar; // if the incoming character is a newline, set a flag // so the main loop can do something about it: if (inChar == '\n') { bStringComplete = true; } else { bStringComplete = false; } } } //=============== //------------------------------------Main Functions----------------------------------------- //SetUp void setup() { // Loop over the pin array and set them all to output: Serial.begin(9600); // Opens serial port, sets data rate to 9600 bps Serial.println("((C))PA3BNX Arduino Doppler"); Serial.println("%999"); //Squelch always closed at start pinMode(refpa3bnx,OUTPUT); digitalWrite(refpa3bnx,LOW); pinMode( kPinAnalog,INPUT); //Okay here ???? pinMode(kPin[5],OUTPUT); //Discharge Pin bc547 digitalWrite(kPin[5],LOW); pinMode(max232Pin[0],OUTPUT); pinMode(max232Pin[1],OUTPUT); digitalWrite(max232Pin[0],LOW); digitalWrite(max232Pin[1],LOW); for (byte i=0; i<4; i++){ pinMode(kPin[i],OUTPUT); pinMode(antPin[i] ,OUTPUT); digitalWrite(antPin[i],LOW); //antPin LOW digitalWrite(kPin[i],LOW); //Set Cap pins to low so the can charge to 1/2U } Average(cNodegrees); //Reset all to 0 EmptyCaps; //All kPins to 1/2 U //Now start ISR interrupt // Timer0 is already used for millis() - we'll just interrupt somewhere // in the middle and call the "Compare A" function below OCR0A = 0xAF; TIMSK0 |= _BV(OCIE0A); // ToDo is there a default timer in microseconds to ? // Interrupt is called once a millisecond // I assume now doppler rotate frequency 4 mSec or 1/.004 = 250 Hz //Measured 244 Hz at refpa3bnx pin } //Main Loop void loop() { // ToDo // GetCapValues // Set the ant1,2,3,4 and refpa3bnx pins ISR // Squelch status // OverFlow Reset the 4 kwadrant capicitors // Calibrate routine (add an degrees offset) // SinCosDetector // Send (averaged) and calibrated degrees out through the serialport // Receive remote serial cmd's like CW/CCW and Degrees //Integer byte swap = antPin[1]; //90 degrees int t; bNoSetKpins = true; GetCapValues(); bNoSetKpins = false; SetKpinsHigh(); sqlstatus = Squelch(); //Squelch status check if (sqlstatus == cSqloverflow || (t > cMaxTime)) { t = 0; bNoSetKpins = true; EmptyCaps(); bNoSetKpins= false; SetKpinsHigh(); } else { //Relaxed sending degrees to serialport if (sqlstatus == cSqlopen2closed && bMultiPathAverage == false) { if (MultiPathDetectSCF == false){ Serial.println(Format3Degrees(Cali(Average(SinCosDetector())))); sqlstatus = cSqlclosed; } } } //Try to read Calibration, CW/CCW, Timing Parameters //000<cr> <lf> from MyMapping.exe as calibrate cmd serialEvent; //Call SerialEvent once in a while if (bStringComplete == true){ //Swap 90 and 270 degrees pins if (inputString == "CCW"){ if (swap != antPin[1]) { swap=antPin[1]; antPin[1]=antPin[3]; antPin[3]=swap; } } else if (inputString == "CW") { if (swap != antPin[1]) { swap=antPin[1]; antPin[1]=antPin[3]; antPin[3]=swap; } } else { Calibrate = inputString.toInt(); } //Always Clear inputString Now inputString=""; } //Do always every loop delay(cMainLoopDelay); //Wait 500 mSec for next try ? fast enough I think t += 1; //Total loops to compared against cMaxTime } //End of sketch --- End code --- |
| PA3BNX:
Hello EveryBody, I got from PE1KQP some very nice links with documentry about radio WO2 and Radar Have fun watching |
| PA3BNX:
Hello Every Body, I got the Arduino mounted on a board with the PCB hole Shield for a doppler am plate RDF (max232). So now I can focus on the arduino sketch Take a loo here PA8W made also a nice Arduino Doppler with 128 by 64 pixel screen. https://www.youtube.com/watch?v=rzyIFLcg6-A&feature=youtu.be |
| PA3BNX:
Hello Every Body, I worked again on the Arduino Sketch It works. I want to make 500 and 3000 Hz doppler rotation adjustments in it with ISR timer interrupt So I could send LOW or HIGH through serial USB/COM and switch teh doppler rotation frequency. (500Hz for nbfm and 3000Hz for wbfm) Any hints how to do that --- Code: ---/* ((C))PA3BNX Arduino Uno REV 3 Sketch Look at http://www.pi4wag.nl/projecten/doppler-peiler-radio-direction-finder Trying to create a SuperSimpleArduinoDoppler on Arduino Uno R3 For this there is a special Arduino Com/USB input in program MyMapping to show the Agrelo(%bbb<cr><lf>) headings on maps No adjustments on the arduino shield it self All adjustmenst like Calibrate-offset and CW/CCW through Serial Port Doppler frequency 500 - 3000 Hz ToDo Squelch level adjust ? ToDo Antenna test 1,2,3,4 Wait 3 seconds then restart scanning ? ToDo Remote CMD's ANT1 ANT2 ANT3 ANT4 CW CCW LOW HIGH (bbb Calibrate) @12-04-2015 @13-04-2015 @15-04-2015 @17-04-2015 @22-04-2015 @24-04-2015 @25-04-2015 @26-04-2015 @27-04-2015 @29-04-2015 @01-05-2015 @02-05-2015 @03-05-2015 @05-05-2015 @06-05-2015 @08-05-2015 @10-05-2015 @12-05-2015 Not quite ready yet but working! I want LOW and HIGH working Doppler ISR rotate Routines 500 Hz and 3000Hz(Now it runs only on 244 Hz) Arrays are zero based !!!! Explaining Arduino pins: antPins[4] Connect to antenna switcher pins refpa3bnx Connect to audio lowpass filter for soundcard referency input kPins[4] Connect to kwadrant C's 4u7 kPinAnalogue Connect to sum point of 4 cap's max232Pin[2] for Am WhatsonWatt DF through max232 external chip + and - 12 V */ //Byte= 0>255 //Int= -32768>32767 //String Serial params String inputString=""; //Received serial string //Boolean boolean bStringComplete=false; //Complete '\n' rxed serial string boolean bNoSetKpins=false; //Do not change kPin[] because I am reading/empty them now boolean bNoAntScan=false; //Do not change antPins while testing one antenna boolean bMultiPathAverage=false; //Multipath heading found in received headings from Averaged //Const Integer //Must be modified to right pin number arduino and arduino shield harddware //Antenna Control Pins & refpa3bnx //Never use pins 0 and 1 because the UART must also function //So I started with pin nbr 2 byte antPin[4]={2,3,4,5}; //Set antenna control pins (Not const because it can be CCW/CW) const byte max232Pin[2]={7,8}; //Set Max232Pin vor AM plate antenna const byte refpa3bnx=6; //Pin for Referency frequency output to soundcard const byte cHigh=9; //All kPins High Only Used in function SetKpins //Kwadrant Capicity switches & analogue SCF read pin const byte kPin[5]={9,10,11,12}; //4 pins caps 4u7 const byte kPinAnalog=0; //A0 read voltage across one 4u7 cap pin A0 to A5 const int cOffset=511; // .5 * 1023 caps offset //Squelch Signals const byte cSqlclosed=0; const byte cSqlclosed2open=1; const byte cSqlopen2closed=2; const byte cSqloverflow=3; //Capicitors are full // //NoDegreesMaxMinValues const int cNodegrees=999; //Squelch No Signal or cSqlopen2closed Clear avDegrees and set avDegrees to cNodegrees const int cReset=888; //Clear Average and avDegrees const int cMaxTime=60; //15 Sec/cMainLoopDelay Max time 60 * 250 = 15 Sec const int cMainLoopDelay=1000; //How fast the main loop runs in mSec const int cMinAudioAmplitude=60; //There is enough signal to SinCosDetect const int cMaxSymmetric=175; //Max Sym in MultiPathSCF //Float const //const float pi = 4 * atan(1); //PI 3.14159 //const float rad = pi/180; const float rad1=180/PI; //57.295827 //const float TwoPi = 2 * pi; //TWO_PI //Integer //Array with the 4 kwandrant analogue cap tensions These can be -511 to +511 byte sqlstatus=cSqlclosed; byte swap=antPin[1]; //90 degrees Loop int Cap[4]={0,0,0,0}; int Calibrate=0; //Calibrate degrees default int tMaxTime=0; //Used in Loop //------------ISR Main Interrupt //This runs always-------------------- ISR(TIMER0_COMPA_vect) { static byte c; //Do the Ant and Cap rotation here if (c==4){ c=0; } if (bNoAntScan == false) { SetAntPins(c); SetKpins(c); SetMax232Pins(c); } //Always increment c++; } //---------Functions now------------------- //Listen/Test on each antenna separate for about 3 sec's void AntTest(byte a){ bNoAntScan = true; //Switch all Low for (byte i=0;i<4;i++) { digitalWrite(antPin[i],LOW); } //Switch one High digitalWrite(antPin[a],HIGH); SetMax232Pins(a); delay(3000); //Switch again to Low digitalWrite(antPin[a],LOW); bNoAntScan = false; a+=1; Serial.print(F("Ant test ")); //F means keep Ant test in ROM Serial.println(a); } //Max232Pins for AM Wattson Watt RDF void SetMax232Pins(byte t){ switch (t){ case 0: digitalWrite(max232Pin[0],HIGH); digitalWrite(max232Pin[1],LOW); break; case 1: digitalWrite(max232Pin[0],HIGH); digitalWrite(max232Pin[1],HIGH); break; case 2: digitalWrite(max232Pin[0],LOW); digitalWrite(max232Pin[1],LOW); break; case 3: digitalWrite(max232Pin[0],LOW); digitalWrite(max232Pin[1],HIGH); break; } } //Antenna Control Lines Just counts 1234 1234 etc void SetAntPins(byte t){ switch (t){ case 0: digitalWrite(antPin[0], HIGH); digitalWrite(antPin[3], LOW); digitalWrite(refpa3bnx,HIGH); break; case 1: digitalWrite(antPin[1], HIGH); digitalWrite(antPin[0], LOW); break; case 2: digitalWrite(antPin[2], HIGH); digitalWrite(antPin[1], LOW); digitalWrite(refpa3bnx,LOW); break; case 3: digitalWrite(antPin[3], HIGH); digitalWrite(antPin[2], LOW); break; } } //Set kwadrant Cap Pins according to antPins void SetKpins(byte t){ //Nothing Todo now if (bNoSetKpins==true){return;} //Set all HIGH for (byte i=0;i<4;i++) { digitalWrite(kPin[i],HIGH); } //Set the pin LOW to charge the cap //Only if t not cHigh if (t != cHigh) { digitalWrite(kPin[t],LOW); } } //Get the 4 analogue value's in Cap[] void GetCapValues(){ //This leaves all kPin[] HIGH when finished //Set all kwadrant Cap Pins HIGH for (byte i=0;i<4;i++) { digitalWrite(kPin[i],HIGH); } //Read these one by one for (byte i=0;i<4;i++) { digitalWrite(kPin[i],LOW); //delayMicroseconds(100); Cap[i]=analogRead(kPinAnalog)-cOffset; delayMicroseconds(150); //Ref say about .1 milli Sec to settel analogue digitalWrite(kPin[i],HIGH); } } //Empty the 4 capicitors by discharging to 1/2 U //This function leaves all kPin[] = HIGH void EmptyCaps(){ Serial.println(F("EmptyCaps")); byte i; for (i=0;i<4;i++) { digitalWrite(kPin[i],LOW); } delay(1000); for (i=0;i<4;i++) { digitalWrite(kPin[i],HIGH); } } //-------------Squelch----------------------- int Squelch(){ //Return the sqlstatus //Try Find a full cap int x; int z; //Find cap with highest voltage/tension //Biggest value = cOffset (511) for(byte i=0;i<4;i++) { z=abs(Cap[i]); if (z>0); { x=z; } } //See if there is a Full Cap //cOffset = Biggest value if (x>=cOffset) { return cSqloverflow; //Caps are full so need discharged } else if (x>=cMinAudioAmplitude) { return cSqlclosed2open; } else if (sqlstatus==cSqlclosed2open && x<cMinAudioAmplitude) { return cSqlopen2closed; } else { return cSqlclosed; } } //Detect Multipath in SCF Caps boolean MultiPathDetectSCF(){ //Calc average of 4 kwadrants //If to large asymetric value return true //Can it do also the Quality 1-9 ? int x; for (int i=0;i<4;i++){ x+=Cap[i]; } //150 of max 510 is the MultiPath level ? if (abs(x)>cMaxSymmetric){ return true; } else { return false; } } //Calibrate int Cali(int d){ return LimitDegrees360(Calibrate+d); } //Return Agrelo formatted string % and 3 digits always String Format3Degrees(int d){ String str; int digits[3]; int reminder; digits[0]=d/100; reminder=d%100; digits[1]=reminder/10; reminder=reminder%10; digits[2]=reminder; str+='%'; str+=digits[0]; str+=digits[1]; str+=digits[2]; return str; } //Limit Degrees 0 to 360 degrees int LimitDegrees360(int d){ //Limit degrees 0 to 360 here //If 999 then return 999 if (d==cNodegrees) { return cNodegrees; } else { int x; x = d % 360; if (x<0) { x += 360; return x; } } } //Average int Average(int d){ //If d = 999 (cNoDegrees) then reset average and return last avDegrees //If d = 888 (cReset) then Reset all and put last avDegrees back in arrays //Always return avDegrees and Set bMultiPath //Integer static int sum[4]={0,0,0,0}; //Sum of counts for each kwadrant static int c[4]={0,0,0,0}; //Cap tension/voltage in each kwadrant static int avDegrees=cNodegrees; //Averaged degrees int xx[4]={0,0,0,0}; //Adjacent kwadrants counts int z=0; //Most adjacent headings int z1=0; //Other two kwandants headings Multipath int y=0; //Index where the most headings are //Reset/clear and return cNodegrees or last avDegrees switch (d){ case cNodegrees: //Reset and Clear for (byte i=0;i<4;i++) { sum[i]=0; c[i]=0; } bMultiPathAverage = false; avDegrees = cNodegrees; return avDegrees; case cReset: //Reset and fill with avDegrees //Reset for (byte i=0;i<4;i++) { sum[i]=0; c[i]=0; } //Fill with last avDegrees d=avDegrees; } if (d>=0 && d<90){ sum[0]+=d; c[0]++; } if (d>=90 && d<180){ sum[1]+=d; c[1]++; } if (d>=180 && d<270){ sum[2]+=d; c[2]++; } if (d>=270 && d<=360){ sum[3]+=d; c[3]++; } //No degrees found if (c[0]+c[1]+c[2]+c[3] == 0) { bMultiPathAverage=false; avDegrees=cNodegrees; return avDegrees; } //Find 2 adjacent kwadrants with hold most counts //Count all adjacents kwadrants xx[0]=c[0]+c[1]; xx[1]=c[1]+c[2]; xx[2]=c[2]+c[3]; xx[3]=c[3]+c[0]; //Find out in witch two kwadrants the most headings are for (byte i=0;i<4;i++){ if (xx[i]>=z){ z=xx[i]; //Most Headings y=i; //Witch 2 adjacent Array Index } } //Check for multipath kwadrants switch(z){ case 0: z1=2; break; case 1: z1=3; break; case 2: z1=0; break; case 3: z1=1; break; } if (xx[z]>xx[z1]){ bMultiPathAverage=false; } else { bMultiPathAverage=true; } //Average the 2 most counts kwadrants switch(y){ case 0: avDegrees=(sum[0]+sum[1])/c[y]; break; case 1: avDegrees=(sum[1]+sum[2])/c[y]; break; case 2: avDegrees=(sum[2]+sum[3])/c[y]; break; case 3: if (c[3]==0 && c[0]>0){ avDegrees=sum[0]/c[0]; break; } if (c[3]>0 && c[0]==0){ avDegrees=sum[3]/c[3]; break; } if (c[3]>0 && c[0]>0){ avDegrees=LimitDegrees360(((sum[3]/c[3])+((sum[0]/c[0])+360)/2)); break; } } return avDegrees; } //SinCosDetector Find the degrees from the 4 Cap[] tensions int SinCosDetector(){ int SinSum; int CosSum; //In Cap[] is the tension value of 1 of the 4 C'S //Serial.println(Cap[0]); //Serial.println(Cap[1]); //Serial.println(Cap[2]); //Serial.println(Cap[3]); SinSum=Cap[0]-Cap[2]; CosSum=Cap[1]-Cap[3]; if (SinSum==0 && CosSum==0){ return cNodegrees;//No Signal } else { //Serial.println(atan2(SinSum,CosSum)*rad1); //Added 90 degrees so it's the same as zerocrossdetection return LimitDegrees360((atan2(SinSum,CosSum)*rad1)+90); } } //=============SerialRx Event=========================== void serialEvent() { while (Serial.available()) { //get the new byte: char inChar=(char)Serial.read(); // if the incoming character is a newline, set a flag // so the main loop can do something about it: if (inChar=='z'||inChar=='\r'||inChar=='\n'||inputString.length() > 4 ){ bStringComplete=true; } else { //add it to the inputString: inputString+=inChar; } } } //======================================================= //========================================= boolean CheckOnlyNbr(String str){ //Check for only numbers 0 to 9 in the string //48=0 57=9 for (unsigned j=0;j<str.length();j++){ byte x=str.charAt(j); if ((x<48)||(x>57) ) { return false; } } return true; } //======================================== //------------------------------------Main Functions----------------------------------------- //SetUp void setup() { Serial.begin(9600); // Opens serial port, sets data rate to 9600 bps Serial.println("((C))PA3BNX Arduino Doppler"); Serial.println("%999"); //Squelch always closed at start //Serial.println(Format3Degrees(cNodegrees)); //Squelch always closed at start pinMode(refpa3bnx,OUTPUT); digitalWrite(refpa3bnx,LOW); pinMode(max232Pin[0],OUTPUT); pinMode(max232Pin[1],OUTPUT); digitalWrite(max232Pin[0],LOW); digitalWrite(max232Pin[1],LOW); for (byte i=0;i<4;i++) { pinMode(antPin[i],OUTPUT); pinMode(kPin[i] ,OUTPUT); digitalWrite(antPin[i],LOW); //antPin LOW = OFF digitalWrite(kPin[i],LOW); //Set Cap pins to low so the can charge to 1/2U } // Now start ISR interrupt // Timer0 is already used for millis() - we'll just interrupt somewhere // in the middle and call the "Compare A" function below OCR0A=0xAF; TIMSK0|=_BV(OCIE0A); // ToDo is there a default timer in microseconds to ? // Interrupt is called once a millisecond // I assume now doppler rotate frequency 4 mSec or 1/.004 = 250 Hz //Measured 244 Hz at refpa3bnx pin } //Main Loop void loop() { // ToDo // GetCapValues // Squelch status // OverFlow Reset the 4 kwadrant capicitors // Calibrate routine (add an degrees offset) // SinCosDetector // Send (averaged) and calibrated degrees out through the serialport // Receive remote serial cmd's like CW/CCW and Degrees bNoSetKpins=true; GetCapValues(); //Fill Values in Cap[] //Leaves all Kpins HIGH when finished bNoSetKpins=false; sqlstatus=Squelch(); //Squelch status check uses Cap[] values if (sqlstatus==cSqlclosed) { tMaxTime=0; Average(cNodegrees); //Clear all } else { tMaxTime+=1; //Total loops to compared against cMaxTime } if (sqlstatus==cSqloverflow||(tMaxTime>=cMaxTime)) { bNoSetKpins=true; EmptyCaps();//Leaves all Kpins HIGH bNoSetKpins=false; } else { //Not Ready here but working //Relaxed sending degrees to serialport boolean bSCF; byte x1; byte x2; //bSCF=MultiPathDetectSCF(); x1=SinCosDetector(); //Never add a MultiPath SCF value to Average if (bSCF==false) { x2=Average(x1); } if (sqlstatus==cSqlopen2closed) { if (bMultiPathAverage==false) { Serial.println(Format3Degrees(Cali(x2))); { //Always Squelch Closed and Reset Average Serial.println(Format3Degrees(cNodegrees)); //Squelch Closed } } } else if (sqlstatus==cSqlclosed2open) { if (bMultiPathAverage==false) { Serial.println(Format3Degrees(Cali(x2))); } } } //Try to read Calibration, CW/CCW, Timing Parameters //000<cr> <lf> from MyMapping.exe as calibrate cmd serialEvent(); //Call SerialEvent once in a while if (bStringComplete==true){ //Swap 90 and 270 degrees pins if (inputString=="CW") { Serial.println(inputString); if (swap!=antPin[1]) { swap=antPin[1]; antPin[1]=antPin[3]; antPin[3]=swap; } } else if (inputString=="CCW") { Serial.println(inputString); if (swap!=antPin[3]) { swap=antPin[3]; antPin[3]=antPin[1]; antPin[1]=swap; } } else if (inputString=="ANT1") { AntTest(0); } else if (inputString=="ANT2") { AntTest(1); } else if (inputString=="ANT3") { AntTest(2); } else if (inputString=="ANT4") { AntTest(3); } else if (inputString=="LOW") { //ToDo ISR 500 Hz } else if (inputString=="HIGH") { //ToDo ISR 3000 Hz } else { //Try Calibrate offset if (CheckOnlyNbr(inputString)==true) { int x; x=inputString.toInt(); if (x>=0 && x <=360) { Calibrate=x; Serial.print(F("Calibrate=")); Serial.println(Calibrate); } } } //Now clear inputString because all done inputString=""; bStringComplete=false; } //Do always every loop //Reset if(tMaxTime>=cMaxTime) { tMaxTime=0; if (sqlstatus==cSqlclosed2open) { Average(cReset); //Clear and Reset avDegrees } } //Wait 250 a 1000 mSec for next try ? fast enough I think delay(cMainLoopDelay); } //End of sketch Last bracket of Loop --- End code --- |
| Navigation |
| Message Index |
| Next page |
| Previous page |