Created
September 13, 2014 18:15
-
-
Save jackdev23/2fb454676ddff4e4f005 to your computer and use it in GitHub Desktop.
Arduino:AAFinalMike
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////// | |
//Antenna analyzer KL V2.1 // | |
///////////////////////////// | |
/** Copyright 2014 Luca Facchinetti, IW2NDH | |
All trademarks referred to in source code and documentation are copyright their respective owners. | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 3 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
If you offer a hardware kit using this software, show your appreciation by sending the author | |
a complimentary kit or a donation to a cats refuge ;-) | |
*/ | |
#include <avr/eeprom.h> | |
#include "U8glib.h" | |
// #include "M2tk.h" | |
// #include "utility/m2ghu8g.h" | |
#include <AH_AD9850.h> | |
#include <rotary.h> | |
#include <OneButton.h>// http://www.mathertel.de/Arduino/OneButtonLibrary.aspx | |
U8GLIB_64128N u8g(13, 11, 10, 9, 8); //SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9 | |
AH_AD9850 AD9850(5, 6, 7, 4); //AH_AD9850(int CLK, int FQUP, int BitData, int RESET); | |
Rotary r = Rotary(2, 3); | |
// Setup a new OneButton on pin 12. | |
OneButton button(A1,true); | |
float bandSwr[7]; | |
float freqBand[7] = {3650000.0, 7100000.0,10125000.0, 14175000.0,18118000.0, 21225000.0, 28850000.0}; | |
const byte lcdW = 128 ; | |
const byte lcdH = 64 ; | |
const byte fontWidth = 5 ; | |
const byte fontHeigth = 8 ; | |
const byte totSpan = 9; | |
byte SWR[lcdW]; | |
//byte Z[84]; | |
float minSwr; | |
float maxSwr; | |
uint32_t next_state_sweep = 0; | |
byte select_display = 0; | |
byte menu_redraw_required = 0; | |
byte doubleClicked = 0; | |
byte modSpan = 0; | |
byte posInput = 0; | |
byte sign = 0; // negative | |
float spanValue[totSpan] = {25000.0, 50000.0,100000.0, 250000.0,500000.0, 1000000.0, 2500000.0, 5000000.0,10000000.0}; | |
struct settings_t | |
{ | |
int spanIdx; | |
float freqCenter; | |
} settings; | |
//from radians to degrees | |
const float R2d = 57.296; | |
//Standard characteristic impedance | |
const float Z0 = 50.000; | |
float Angle ; | |
float Mag ; | |
float Ximp ; | |
float Rimp ; | |
float Zimpl ; | |
float Swr ; | |
void Docalcswr(){ | |
float Tmpsa ; | |
float Tmpsb ; | |
float Tmpsc ; | |
//adc variables | |
float Adcphase; | |
float Adcmagnitude; | |
float Returnloss; | |
//float refer = 5.0*analogRead(A1)/1023; | |
Adcphase = 1.8 * analogRead(A2)/1023; | |
Adcmagnitude = 1.8 *analogRead(A0)/1023; | |
Returnloss = (60.00 * Adcmagnitude /1.8); | |
Returnloss = Returnloss - 30.00 ; | |
Angle = (180.0 * Adcphase /1.8) -90; | |
Tmpsa = Returnloss / 20.00; | |
Tmpsb = 10.00; | |
Mag = pow(Tmpsb , Tmpsa); | |
Mag = 1.00 / Mag; | |
Tmpsa = 1.00 + Mag; | |
Tmpsb = 1.00 - Mag; | |
Tmpsc = Tmpsa / Tmpsb; | |
Swr = abs(Tmpsc); | |
// Serial.print("Adcmagnitude "); | |
// Serial.print(Adcmagnitude); | |
// Serial.print(" Returnloss "); | |
// Serial.print(Returnloss); | |
// Serial.print(" A2 "); | |
// Serial.print(analogRead(A2)); | |
// Serial.print(" A0 "); | |
// Serial.println(analogRead(A0)); | |
} | |
void Docalcall(){ | |
Docalcswr(); | |
float Tmpsa ; | |
float Tmpsb ; | |
float Tmpsc ; | |
float Rrsqrtmp ; | |
float Sssqrtmp ; | |
float F ; | |
float G ; | |
float Rr ; | |
float Ss ; | |
Tmpsa = Angle / R2d; | |
F = cos(Tmpsa); | |
G = sin(Tmpsa); | |
Rr = F * Mag; | |
Ss = G * Mag; | |
Tmpsa = 1.00 - Rr; | |
Rrsqrtmp = Tmpsa * Tmpsa; | |
Sssqrtmp = Ss * Ss; | |
Tmpsa = Rrsqrtmp + Sssqrtmp; | |
Tmpsb = 2.00 * Ss; | |
Tmpsc = Tmpsb / Tmpsa; | |
Tmpsa = Tmpsc * Z0; | |
Ximp = abs(Tmpsa); | |
Tmpsa = Rr * Rr; | |
Tmpsb = 1.0 - Tmpsa; | |
Tmpsa = Tmpsb - Sssqrtmp; | |
Tmpsb = Rrsqrtmp + Sssqrtmp; | |
Tmpsc = Tmpsa / Tmpsb; | |
Tmpsa = Tmpsc * Z0; | |
Rimp = abs(Tmpsa); | |
Tmpsa = Rimp * Rimp; | |
Tmpsb = Ximp * Ximp; | |
Tmpsc = Tmpsa + Tmpsb; | |
Zimpl = sqrt(Tmpsc); | |
} | |
void calcParameters(int k, float stepSpan){ | |
float freq; | |
float tempSwr; | |
freq = settings.freqCenter + (k-lcdW/2)* stepSpan; | |
if (freq <= 0) freq = 1000000.0; | |
AD9850.set_frequency(freq); | |
delay(2); | |
Docalcswr(); | |
Swr = max(1.00,Swr); | |
minSwr = min(minSwr,Swr); | |
maxSwr = max(maxSwr,Swr); | |
tempSwr = min (3.0, Swr); | |
SWR[k] = 8+(46 - round(23*(tempSwr - 1))); //MAX SWR = 3.0 | |
} | |
void printReverse(u8g_uint_t x, u8g_uint_t y,const char *s){ | |
u8g_uint_t w = u8g.getStrWidth(s); | |
u8g.drawBox(x, y - 7, w, 9); // draw cursor bar | |
u8g.setDefaultBackgroundColor(); | |
u8g.drawStr(x,y,s); | |
u8g.setDefaultForegroundColor(); | |
} | |
void creaGrid(){ | |
u8g_uint_t p0 = lcdH - 2; | |
for (int i = 1 ;i < 2; i++){ | |
u8g.drawHLine(0,(i*22)+fontHeigth,lcdW - 1); | |
} | |
for (int i = 0 ;i < 9; i++){ | |
u8g.drawVLine(64+(i-4)*14,fontHeigth,46); | |
} | |
u8g.drawCircle(64,49+fontHeigth,2); | |
if (settings.freqCenter >9999999) u8g.setPrintPos(30, p0); | |
else u8g.setPrintPos(35, p0); | |
u8g.print(settings.freqCenter/1000000,3); | |
if (spanValue[settings.spanIdx] >9999999) u8g.setPrintPos(94, p0); | |
else u8g.setPrintPos(99, p0); | |
u8g.print(spanValue[settings.spanIdx]/1000000,3); | |
u8g.drawRFrame(0,fontHeigth,lcdW,46, 1); | |
u8g.drawStr(0, fontHeigth-1,"SWR"); | |
u8g.setPrintPos(42, fontHeigth-1); | |
u8g.print(minSwr, 2); | |
u8g.setPrintPos(96, fontHeigth-1); | |
u8g.print(maxSwr, 2); | |
if (!modSpan){ | |
printReverse(0, p0 ,"freq"); | |
u8g.drawStr(70, p0 ,"span"); | |
}else{ | |
u8g.drawStr(0, p0 ,"freq"); | |
printReverse(70, p0 ,"span"); | |
} | |
} | |
void printSwr(){ | |
for (int k = 0;k < lcdW -1; k++){ | |
u8g.drawLine(k,SWR[k],k+1,SWR[k+1]); | |
// u8g.drawCircle(k,Z[k], 1, U8G_DRAW_ALL) ; | |
} | |
} | |
void swrFrame(u8g_uint_t pos, float swrVal){ | |
u8g.drawBox(50, pos, 77*((min(swrVal,2.5)-1.0)/1.5), 6); | |
u8g.drawFrame(50, pos, 77, 6); | |
u8g.drawVLine(76, pos,5); | |
u8g.drawVLine(102, pos,5); | |
} | |
// void barraZ(u8g_uint_t pos, float val){ | |
// u8g.drawBox(50, pos, 77*((min(val,100))/100), 6); | |
// u8g.drawFrame(50, pos, 77, 6); | |
// u8g.drawVLine(88,pos,6); | |
// u8g.setPrintPos(22,pos+7); | |
// u8g.print(val,1); | |
// } | |
void creaBand(){ | |
u8g.setPrintPos(76,7); | |
u8g.print(1.5,1); | |
u8g.setPrintPos(102,7); | |
u8g.print(2.0,1); | |
for (int i = 0 ;i < 7; i++){ | |
u8g_uint_t pos = (8 * i) + 10; | |
u8g.setPrintPos(0, pos + 5); | |
u8g.print(freqBand[i]/1000000,3); | |
swrFrame(pos,bandSwr[i]); | |
} | |
} | |
// void creaZimp(){ | |
// u8g.drawStr(0,8,"freq:"); | |
// if (settings.freqCenter >9999999) u8g.setPrintPos(50,8); | |
// else u8g.setPrintPos(56,8); | |
// u8g.print(settings.freqCenter,0); | |
// u8g.drawStr(0,18,"SWR"); | |
// swrFrame(12,Swr); | |
// u8g.setPrintPos(20,18); | |
// u8g.print(Swr,2); | |
// u8g.drawStr(0,48,"R"); | |
// barraZ(41,Rimp); | |
// if (sign == 0){ | |
// u8g.drawStr(0,39,"Ph +"); | |
// u8g.drawStr(0,55,"Xc +"); | |
// printReverse(0,28,"short"); | |
// } | |
// else { | |
// u8g.drawStr(0,39,"Ph -"); | |
// u8g.drawStr(0,55,"Xl -"); | |
// printReverse(105,28,"long"); | |
// } | |
// u8g.setPrintPos(22,39); | |
// u8g.print(abs(Angle),1); | |
// barraZ(49,Ximp); | |
// u8g.drawStr(0,63,"Z"); | |
// barraZ(57,Zimpl); | |
// } | |
// uint8_t update_graph_Zimp(void) { | |
// if ( next_state_sweep < 2) { | |
// // swr decrease when freq encrease <=> too short <=> X positive (C) <=> sign = 1 | |
// AD9850.set_frequency(settings.freqCenter+100000.0); | |
// delay(10); | |
// Docalcswr(); | |
// float upFreqSwr = Swr; | |
// AD9850.set_frequency(settings.freqCenter); | |
// delay(10); | |
// Docalcall(); | |
// if (upFreqSwr > Swr) | |
// sign = 1;else sign = 0; | |
// next_state_sweep++; | |
// return 0; | |
// }else{ | |
// next_state_sweep = 0; | |
// return 1; | |
// } | |
// } | |
uint8_t update_graph_band(void) { | |
if ( next_state_sweep < 7) { | |
AD9850.set_frequency(freqBand[next_state_sweep]); | |
delay(10); | |
Docalcswr(); | |
bandSwr[next_state_sweep] = Swr; | |
next_state_sweep++; | |
return 0; | |
}else{ | |
next_state_sweep = 0; | |
return 1; | |
} | |
} | |
uint8_t update_graph(void) { | |
if ( next_state_sweep < lcdW) { | |
if(next_state_sweep == 0){ | |
minSwr = 10.00; | |
maxSwr = 1.00; | |
} | |
float s = spanValue[settings.spanIdx]/lcdW; | |
calcParameters(next_state_sweep,s); | |
next_state_sweep++; | |
return 0; | |
}else{ | |
next_state_sweep = 0; | |
return 1; | |
} | |
} | |
// update graphics, will return none-zero if an update is required | |
uint8_t update_graphics(void) { | |
switch (select_display){ | |
case 1: return update_graph_band(); | |
break; | |
// case 2: { | |
// return update_graph_Zimp(); | |
// // } | |
// break; | |
default: return update_graph(); | |
} | |
// no update for the graphics required | |
return 0; | |
} | |
void showCursor(u8g_uint_t x0, u8g_uint_t y0){ | |
u8g.drawBox(x0 + fontWidth*(7-posInput),y0,6,3); | |
} | |
float updateFreq(unsigned char r, float v){ | |
float step = round(pow(10,posInput)); | |
if (r == DIR_NONE ) { | |
// do nothing | |
} | |
else if ((r == DIR_CW) && (v + spanValue[settings.spanIdx]/2 < 54000000.0)) { | |
v = v + step; | |
} | |
else if ((r == DIR_CCW) && (v >= step + 1000000.0)) { | |
v = v - step; | |
} | |
return v; | |
} | |
void updateSpan(unsigned char r){ | |
if (r == DIR_NONE ) { | |
// do nothing | |
} | |
else if (r == DIR_CW) { | |
settings.spanIdx++; | |
} | |
else if (r == DIR_CCW) { | |
settings.spanIdx--; | |
if (settings.spanIdx < 0) settings.spanIdx = totSpan -1; | |
} | |
settings.spanIdx = settings.spanIdx % totSpan; | |
} | |
//================================================================ | |
// overall draw procedure for u8glib | |
void draw(void) { | |
u8g.setDefaultForegroundColor(); | |
switch (select_display){ | |
case 1: creaBand(); | |
break; | |
// case 2: { | |
// creaZimp(); | |
// if (doubleClicked == 1) { | |
// showCursor(50,8); | |
// } | |
// } | |
// break; | |
default: | |
{ creaGrid(); | |
printSwr(); | |
if (doubleClicked == 1) { | |
switch (modSpan){ | |
case 0 : { | |
if (posInput <3) posInput = 3; showCursor(35,lcdH-1); | |
break; | |
} | |
case 1 :{ | |
posInput = 6; | |
showCursor(91,lcdH-1); | |
break; | |
} | |
default: break; | |
} | |
} | |
} | |
} | |
} | |
//================================================================ | |
// Arduino setup and loop | |
void setup(void) { | |
analogReference(EXTERNAL); | |
// initialize serial communication at 9600 bits per second: | |
Serial.begin(9600); | |
//analogReference(EXTERNAL); | |
// pinMode(12, INPUT); | |
// digitalWrite(12,HIGH); | |
PCICR |= (1 << PCIE2); | |
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19) ; | |
// PCICR |= (1 << PCIE0); | |
// PCMSK0 |= (1 << PCINT4); | |
sei(); | |
// link the doubleclick function to be called on a doubleclick event. | |
button.attachDoubleClick(doubleclick); | |
button.attachClick(singleclick); | |
button.attachPress(longclick); | |
u8g.setFont(u8g_font_5x7); | |
eeprom_read_block((void*)&settings, (void*)0, sizeof(settings)); | |
settings.spanIdx = settings.spanIdx % totSpan; | |
if (settings.freqCenter <= 0) | |
{ | |
settings.freqCenter = 7000000.0; | |
} | |
settings.spanIdx = 0; | |
settings.freqCenter = 7000000.0; | |
AD9850.reset(); //reset module | |
delay(1000); | |
AD9850.powerDown(); //set signal output to LOW | |
AD9850.set_frequency(0,0,settings.freqCenter); | |
} | |
void loop() { | |
button.tick(); | |
if ( update_graphics() != 0 | menu_redraw_required != 0) { | |
u8g.firstPage(); | |
do { | |
draw(); | |
} while( u8g.nextPage() ); | |
menu_redraw_required = 0; // menu updated, reset redraw flag | |
} | |
} | |
ISR(PCINT2_vect) { | |
unsigned char result = r.process(); | |
if (doubleClicked) | |
{ | |
if((select_display == 0) && modSpan){ | |
updateSpan(result); | |
} | |
else | |
settings.freqCenter = updateFreq(result, settings.freqCenter); | |
} | |
else if(select_display == 0) modSpan = !modSpan; | |
menu_redraw_required = 1; | |
} | |
void singleclick() {//change position in field | |
if (doubleClicked) { | |
posInput++; | |
posInput = posInput % 7; | |
} | |
menu_redraw_required = 1; | |
} | |
void doubleclick() { //change field | |
doubleClicked = !doubleClicked; | |
if (!doubleClicked) eeprom_write_block((const void*)&settings, (void*)0, sizeof(settings));; | |
menu_redraw_required = 1; | |
} | |
void longclick() { //rotate displays | |
select_display = select_display++; | |
select_display = select_display % 2; | |
posInput = 0; | |
doubleClicked = 0; | |
eeprom_write_block((const void*)&settings, (void*)0, sizeof(settings)); | |
menu_redraw_required = 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment