2017年4月11日 星期二

低成本 頻譜偵測 Arduino 240~930 MHz Spectrum Analyser

2020-10-14 刪除早期版本,以免造成誤解
2018-02-24 <更新>變更參數範圍  訊號偵測CapTime時間內紀錄最大的收訊值預防漏接

使用SI4432模組,快速切換頻率並偵測收訊強度,將指定範圍的信號強度顯示於84×48的LCD畫面上,頻率範圍受限於Sl4432模組可用區間為240~930MHz,晝面顯示為點狀模式時晝面更新較快,但不易讀取訊息,條狀模式易讀取但畫面更新較受限,但成本不到台幣500元,就別太計較了。

單一功能鍵  切換頻譜模式及連續訊號偵測模式。

頻譜模式可調整的有頻率範圍,頻率間隔,信號增益,信號強度範圍,頻率尺規位置。

連續訊號偵測模式可調整的有偵測的頻率,信號增益,偵測的時間間隔。



















/* 

 for Arduino IDE 1.0.6  http://yulie-wu.blogspot.tw/2017/04/arduino-240930-mhz-spectrum-analyser.html
 2018-02-23 debug and 變更參數範圍 改外接天線,預防漏接 偵測CapTime時間內最大的收訊值 
 2017-03-11 add frequency pos 
 2017-03-09 add memory fn & Battery  volt & cus
 2017-03-04 onCase test OK 
 2016-12-23 by yulie~
 */

#include <EEPROM.h>
#include <SPI.h>
//#include <SD.h>
//const int chipSelect = 17;

#include "U8glib.h"
int incomingByte = 0;  // 用來儲存收進來的 data byte
//U8GLIB_PCD8544 u8g(9, 8, 6, 7, 5);    // CLK ,DIN ,CE ,DC ,RST    //for test
U8GLIB_PCD8544 u8g(5, 6, 8, 7, 9);  // CLK ,DIN ,CE ,DC ,RST    //Case OnBoard

#define LINE_MAX 17 
uint8_t line_buf[LINE_MAX] = "U8GLIB Console";
uint8_t line_pos = 0;
// setup a text screen to support scrolling
#define ROW_MAX 6
uint8_t screen[ROW_MAX][LINE_MAX];
uint8_t rows, cols;
uint8_t rssi,keepRssi;
unsigned long t,u,v,y,x;
// line height, which matches the selected font (5x7)
#define LINE_PIXEL_HEIGHT 7
#include <RF22.h>
// Singleton instance of the radio
RF22 rf22;
byte Spectrum_gain = 4; // 預設訊號位準
byte Spectrum_base = 6; // 預設雜訊位準
byte sigDet_gain = 4;   // 預設訊號位準
byte sigDet_base = 16;  // 預設雜訊位準
float sigDet_Frequency = 432.0;
float sigDet_Frequency_1 = 432.0;


byte cus  = 4; // 預設畫面尺規位置 
byte pos  = 40; // 預設 freq target位置
byte j=0;
byte bar=82;//偵測數
byte barW=1;//長條寬度
byte barG=0;//長條圖間隔
byte barT=30;//偵測間隔mS
byte rsi[84];//陣列數量
//int spt[84];//頻譜陣列數

//volatile int encoderPos = 0; // variables changed within interrupts are volatile

String fnStr="spt";
float fScn  = 432.0;          //Step Frequency /MHz
//float fScn1 = 0;
// float fScn = 0.00f;   //Variable to store data read from EEPROM.
//頻譜參數
float fStep=1.0;          //Step Frequency /MHz
float fSta=400.0;         //Start Frequency  /Mhz
float fEnd= fSta + (84 * fStep); 
byte fn,oldFn,sl,sl_1,oldsl = 0;
word CapTime = 200 ;
byte runOne = 0;
//boolean SwMu,SwDn,SwUp = 1;
boolean SwFn = 1;// 不知為何無法整批指定
boolean SwMu = 1;// 不知為何無法整批指定
boolean SwSl = 1;
boolean SwDn = 1;
boolean SwUp = 1;
word oscill = 500 ;

byte val,old_val,count;
byte readrssi;


//rssi 18--> -118dB//rssi 230 --> -2dB
void setup(void) {
  Serial.begin(115200);
  analogReference(INTERNAL);
  pinMode(A0,INPUT_PULLUP);//14 A0 Fn
  pinMode(A1,INPUT_PULLUP);//15 A1 slect
  pinMode(A2,INPUT_PULLUP);//16 A2 up
  pinMode(A3,INPUT_PULLUP);//17 A3 down
  digitalWrite(9,LOW);  
  // digitalWrite(14,LOW);
  if (!rf22.init())
    Serial.println("RF22 init failed");
  rf22.setFrequency(432.0);  // rf22.setModemConfig(RF22::FSK_PN9_Rb2Fd5);
  rf22.setModeRx();  
  delayMicroseconds(200); // Wait for freq to settle    
  for(int i = 0 ; i <= bar ; i++ ){    
    rsi[i]=2;   
  }

  Serial.println("setup ok");
  //    attachInterrupt(1, irRec, HIGH); // encoder pin on interrupt 0 (pin 2)
  //   u8g.setRot180(); for test
       u8g.firstPage(); do {      
       u8g.setFont(u8g_font_6x10);
       u8g.setPrintPos( 0, 7); 
       u8g.print("Easy Spectrum ");
       u8g.setPrintPos( 0, 17); 
       u8g.print("240~930 MHz");
       u8g.setPrintPos( 0, 25); 
       u8g.print("ver 2018-02-24");
       u8g.setPrintPos( 0, 35); 
       u8g.print(" WU YUN CHANG");
       u8g.setPrintPos( 0, 45); 
       u8g.print("Battery:");
       u8g.print(analogRead(A6) * (1.1 / 1024) * 5.51745);
       u8g.print("V"); } 
      while( u8g.nextPage() );
////取得本地設備電池電壓值
// volt = (analogRead(A0) * (1.1 / 1024) * 5.51745) ; // 220K + 48.7k 分壓 , (220 + 48.7)/48.7=5.51745

 delay(5000);
 fn = EEPROM.read(0); 
 // EEPROM.get( eeAddress, fScn );
}

void loop(void) {
  //  if(digitalRead(A0) == 0 && digitalRead(A0) !=  SwMu ){ // 按住連續跑
  if( digitalRead(A0) !=  SwMu ){      //按住 連續跑
    fn++;  if(fn >= 4)fn=0;   SwMu != SwMu; //true 或 false(A0)
    delay(250);
    if( EEPROM.read(0) != fn ){ EEPROM.write(0, fn);}  //設定值改變才會執行 write 一次
  }

  if(millis() - u >= 5000){
    u=millis(); } 

  switch (fn) {
  case 0:{SwFnSpectrum(); Spectrum();} break;  //頻譜 點
  case 1:{SwFnSpectrum(); Spectrum(); } break;   //頻譜 線
  case 2:{SwFnsigDet(); sigDet(); } break; //顯示脈衝訊號 點 
  case 3:{SwFnsigDet(); sigDet(); } break; //顯示脈衝訊號 線
  case 4:{}
  }
}

//================================================================================================================
void Spectrum(){
      float f = fSta;
      fScn = fSta + ((fEnd-fSta)/2);  //for signal  Detect
      fEnd= fSta + (80 * fStep);
      int i=0;
      while( f < fEnd + 1){
        rf22.setFrequency(f);
        delayMicroseconds(1125);//825~1125
       // rsi[i]=(rf22.rssiRead()/gain) - base;
       // if(rsi[i] <= 1)rsi[i] = 1; //2017-03-06 add  
        rsi[i]=constrain(((rf22.rssiRead()/Spectrum_gain) - Spectrum_base), 1,40);
        //  keepRssi=max(keepRssi,rsi[i]);//取得陣列中最大值
        f += fStep;
        i++;
      }
      u8g.firstPage();  
      do {      
 //      u8g.setRot180();
        u8g.setFont(u8g_font_6x10);
        u8g.setPrintPos( 0, 7); 
        if(sl==0){u8g.print("Freq adj:");}
        if(sl==1){u8g.print("Step adj:");u8g.print(fStep);}
        if(sl==2){u8g.print("Gain adj:");u8g.print(Spectrum_gain);}
        if(sl==3){u8g.print("Base adj:");u8g.print(Spectrum_base);}
        if(sl==4){u8g.print("Cus  adj:");u8g.print(cus);}
        if(sl==5){
        u8g.print("Freq:");
        u8g.print(fSta + (pos * fStep),1); 
        u8g.print("MHz");
        for(int j=16;j<40;j+=2)u8g.drawPixel(pos, j ); // Y 軸虛線
      }
      if(sl != 5){
        u8g.setPrintPos( 0, 15); 
        u8g.print(""); 
        u8g.print(fSta,1); 
        u8g.print("~");
        u8g.print(fEnd,1); 
        u8g.print("MHz");}
        for(int j=0;j<84;j+=20)u8g.drawPixel(j, 18 + cus ); 
        for(int j=0;j<84;j+=10)u8g.drawPixel(j, 19 + cus ); 
       // for(int j=13;j<84;j+=20)u8g.drawPixel(j, 19 + cus );
       // u8g.drawFrame(2, 16 , 1, 32); 
       // u8g.drawPixel(0, 18 );u8g.drawPixel(20, 18 );u8g.drawPixel(40, 18 );u8g.drawPixel(60, 18 );u8g.drawPixel(80, 18 );
       // u8g.drawPixel(0, 19 );u8g.drawPixel(20, 19 );u8g.drawPixel(39, 19 );u8g.drawPixel(60, 19 );u8g.drawPixel(80, 19 );
       // u8g.drawPixel(10, 19 );u8g.drawPixel(30, 19 );u8g.drawPixel(50, 19 );u8g.drawPixel(70, 19 );
        if(fn == 0)for(byte i=0;i <= bar -2; i++)u8g.drawPixel(i, 48 - rsi[i]);  //點  時間軸強度(drawPixel 最快)
        if(fn == 1)for(byte i=0;i <= bar -2; i++)u8g.drawFrame((barW + barG) * i, 48 - rsi[i], barW, rsi[i]);  //線 時間軸強度(drawFrame 快 )
        // u8g.drawBox((barW + barG) * i, 48 - rsi[i], barW, rsi[i]);   //時間軸強度(drawBox 普)
        // u8g.drawLine( i, 48 - rsi[i], i, 48);  //時間軸強度(drawLine 慢)
       } 
      while( u8g.nextPage() );
    }

//================================================================================================================
void sigDet(){
  if(sigDet_Frequency != sigDet_Frequency_1){       //設定值改變才執行一次
    sigDet_Frequency_1 = sigDet_Frequency;
    rf22.setFrequency(sigDet_Frequency);
  }  
  if(millis() - x >= CapTime){
//    Serial.println(millis() - x);  //for show real CapTime 
    x = millis();
//-----------------------------------------------------------------------------------------------------------------
    if(CapTime <= 80)rsi[0]=constrain(((rf22.rssiRead()/sigDet_gain) - sigDet_base), 1,40);
    if(rsi[0] <= 2)rsi[0] = 2; //2017-03-06 add 
    for(int i = 0 ; i <= bar ; i++ ){ rsi[ bar - i] = rsi[bar - (i+1)]; }
      u8g.firstPage();  
      do {      
 //       u8g.setRot180();
        u8g.setFont(u8g_font_6x10);
        u8g.setPrintPos( 0, 7); 
        if(sl_1==0){ u8g.print("Freq adj:"); }
        if(sl_1==1){ u8g.print("Step adj:");u8g.print(fStep); }
        if(sl_1==2){ u8g.print("CapT adj:");u8g.print(CapTime); }
        if(sl_1==3){ u8g.print("Gain adj:");u8g.print(sigDet_gain); }
        if(sl_1==4){ u8g.print("Base adj:");u8g.print(sigDet_base); }
        u8g.setPrintPos( 0, 15); 
        u8g.print(" ");
        u8g.print(sigDet_Frequency,1);
        u8g.print("MHz");
        if(fn == 2)for(byte i=0;i <= bar; i++){u8g.drawPixel(i, 48 - rsi[i]);}  //點 時間軸強度
        if(fn == 3)for(byte i=0;i <= bar; i++){u8g.drawFrame((barW + barG) * i, 48 - rsi[i], barW, rsi[i]);}  //線 時間軸強度
      } 
      while( u8g.nextPage() );
//-----------------------------------------------------------------------------------------------------------------

  else {
    //rsi[0]=constrain(((rf22.rssiRead()/sigDet_gain) - sigDet_base), 1,40);
    readrssi=constrain(((rf22.rssiRead()/sigDet_gain) - sigDet_base), 1,40);  
    rsi[0] = max(rsi[0],readrssi);  //預防漏接 偵測CapTime時間內最大的收訊值 
    //Serial.println(rsi[0]);
  }  
}


//================================================================================================================
void SwFnSpectrum(){
       if( digitalRead(A1) !=  SwSl ){      //按住 連續跑
        sl++;     
        if(sl >= 6)sl=0; 
        SwSl != SwSl;                       //true 或 false
        delay(250);
      } 
      switch (sl) {
       case 0:{ //adj freq range
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            fSta -= 10 * fStep; SwDn != SwDn; delay(1); }
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            fSta += 10 * fStep; SwUp != SwUp; delay(1); }
            fSta = constrain(fSta, 240, 930); } break;
        
       case 1:{ //adj freq step
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            fStep-=0.1;  SwDn != SwDn; delay(1);}
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            fStep+=0.1; SwUp != SwUp; delay(1); }
            fStep = constrain(fStep, 0.1, 5.0);  } break;

       case 2:{//adj GAIN
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            Spectrum_gain++; SwDn != SwDn; delay(1); }
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            Spectrum_gain--; SwUp != SwUp; delay(1); }
            Spectrum_gain = constrain(Spectrum_gain, 1, 32);}  break;

      case 3:{//adj base
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            Spectrum_base++; SwDn != SwDn; delay(80); }
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            Spectrum_base--; SwUp != SwUp; delay(80); }
            Spectrum_base = constrain(Spectrum_base, 1, 64); }  break;
          
      case 4:{//adj cus
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            cus++; SwDn != SwDn; delay(5); }
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            cus--; SwUp != SwUp; delay(5); }
            cus = constrain(cus, 1, 30); }  break;
          
      case 5:{//adj pos
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            pos--; SwDn != SwDn; delay(2);  }
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            pos++; SwUp != SwUp; delay(2);  }
            pos = constrain(pos, 0, 81); }  break;
      } 
}

//================================================================================================================
void SwFnsigDet(){
        if( digitalRead(A1) !=  SwSl ){      //按住 連續跑
        sl_1++;     
        if(sl_1 >= 5)sl_1=0; 
        SwSl != SwSl; //true 或 false
        delay(250);
      } 
      switch (sl_1) {
       case 0:{ //adj freq range
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            sigDet_Frequency -=  fStep; SwDn != SwDn; delay(200); }
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            sigDet_Frequency +=  fStep; SwUp != SwUp; delay(200); }
            sigDet_Frequency = constrain(sigDet_Frequency, 240, 960); } break;

       case 1:{ //adj freq step
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            fStep-=0.1; SwDn != SwDn; delay(100);}
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            fStep+=0.1; SwUp != SwUp; delay(100);}
            fStep = constrain(fStep, 0.1, 5.0);      }  break;
        
       case 2:{ //adj cap time
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            if(CapTime <= 10 && CapTime >= 1 ) CapTime-= 1;
            if(CapTime <= 100 && CapTime >= 20 ) CapTime-= 10;
            if(CapTime >= 200 )  CapTime-= 100;
            SwDn != SwDn;  delay(100); }
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            if(CapTime >= 100 )  CapTime+= 100;
            if(CapTime <= 100 && CapTime >= 10 ){CapTime+= 10;}
            if(CapTime <= 9 && CapTime >= 1 ) CapTime+= 1;
            SwUp != SwUp; delay(100); }
            CapTime = constrain(CapTime, 1, 5000); }  break;

       case 3:{//adj GAIN
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){   // 按住連續跑
            sigDet_gain++; SwDn != SwDn; delay(100); }
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑
            sigDet_gain--; SwUp != SwUp; delay(100); }
            sigDet_gain = constrain(sigDet_gain, 1, 32);  } break;

       case 4:{//adj base
          if(digitalRead(A3) == 0 && digitalRead(A3) !=  SwDn ){    // 按住連續跑+
            sigDet_base++; SwDn != SwDn; delay(80); }               // 連續速率
          if(digitalRead(A2) == 0 && digitalRead(A2) !=  SwUp ){    // 按住連續跑-
            sigDet_base--; SwUp != SwUp; delay(80); }               // 連續速率
            sigDet_base = constrain(sigDet_base, 1, 80);  } break;
      } 
}



2017年2月8日 星期三

Arduino UNO + 2.4 吋 TFT 觸控螢幕

Arduino UNO +  2.4" LCD   Shield (ILI9325 )

Download & Install  Library

1. https://github.com/adafruit/Adafruit-GFX-Library
2. https://github.com/adafruit/TFTLCD-Library
3. https://github.com/adafruit/Touch-Screen-Library







open file ...








修改 & 新增紅字部分

// Paint example specifically for the TFTLCD breakout board.

// If using the Arduino shield, use the tftpaint_shield.pde sketch instead!
// DOES NOT CURRENTLY WORK ON ARDUINO LEONARDO

#include <Adafruit_GFX.h>    // Core graphics library

#include <Adafruit_TFTLCD.h> // Hardware-specific library
#include <TouchScreen.h>

#if defined(__SAM3X8E__)

    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:

// For the Arduino Uno, Duemilanove, Diecimila, etc.:
//   D0 connects to digital pin 8  (Notice these are
//   D1 connects to digital pin 9   NOT in order!)
//   D2 connects to digital pin 2
//   D3 connects to digital pin 3
//   D4 connects to digital pin 4
//   D5 connects to digital pin 5
//   D6 connects to digital pin 6
//   D7 connects to digital pin 7

// For the Arduino Mega, use digital pins 22 through 29

// (on the 2-row header at the end of the board).
//   D0 connects to digital pin 22
//   D1 connects to digital pin 23
//   D2 connects to digital pin 24
//   D3 connects to digital pin 25
//   D4 connects to digital pin 26
//   D5 connects to digital pin 27
//   D6 connects to digital pin 28
//   D7 connects to digital pin 29

// For the Arduino Due, use digital pins 33 through 40

// (on the 2-row header at the end of the board).
//   D0 connects to digital pin 33
//   D1 connects to digital pin 34
//   D2 connects to digital pin 35
//   D3 connects to digital pin 36
//   D4 connects to digital pin 37
//   D5 connects to digital pin 38
//   D6 connects to digital pin 39
//   D7 connects to digital pin 40


#define XP 7   // can be a digital pin

#define YP A2  // must be an analog pin, use "An" notation!
#define XM A1  // must be an analog pin, use "An" notation!
#define YM 6   // can be a digital pin

//觸控板對應螢幕範圍
#define TS_MINX 190
#define TS_MINY 140
#define TS_MAXX 880
#define TS_MAXY 900

// For better pressure precision, we need to know the resistance

// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
// TouchScreen ts = TouchScreen(7, A2, A1, 6, 300);
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
// optional
#define LCD_RESET A4

// Assign human-readable names to some common 16-bit color values:

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF


Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);


#define BOXSIZE 40

#define PENRADIUS 3 //筆劃粗細
int oldcolor, currentcolor;

void setup(void) {

  Serial.begin(9600);
  Serial.println(F("Paint!"));

  tft.reset();

  
  uint16_t identifier = tft.readID();

  if(identifier == 0x9325) {

    Serial.println(F("Found ILI9325 LCD driver"));
  } else if(identifier == 0x9328) {
    Serial.println(F("Found ILI9328 LCD driver"));
  } else if(identifier == 0x7575) {
    Serial.println(F("Found HX8347G LCD driver"));
  } else if(identifier == 0x9341) {
    Serial.println(F("Found ILI9341 LCD driver"));
  } else if(identifier == 0x8357) {
    Serial.println(F("Found HX8357D LCD driver"));
  } else {
    Serial.print(F("Unknown LCD driver chip: "));
    Serial.println(identifier, HEX);
    Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:"));
    Serial.println(F("  #define USE_ADAFRUIT_SHIELD_PINOUT"));
    Serial.println(F("should appear in the library header (Adafruit_TFT.h)."));
    Serial.println(F("If using the breakout board, it should NOT be #defined!"));
    Serial.println(F("Also if using the breakout, double-check that all wiring"));
    Serial.println(F("matches the tutorial."));
    return;
  }
  tft.setRotation(2);//0-3
  tft.begin(identifier);

  tft.fillScreen(BLACK);


  tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);

  tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
  tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN);
  tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN);
  tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE);
  tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA);
  // tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, WHITE);

  tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);

  currentcolor = RED;

  pinMode(13, OUTPUT);


}


#define MINPRESSURE 10

#define MAXPRESSURE 1000

void loop()

{
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();
  digitalWrite(13, LOW);

  // if sharing pins, you'll need to fix the directions of the touchscreen pins

  //pinMode(XP, OUTPUT);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  //pinMode(YM, OUTPUT);

  // we have some minimum pressure we consider 'valid'

  // pressure of 0 means no pressing!

  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {

    /*
    Serial.print("X = "); Serial.print(p.x);
    Serial.print("\tY = "); Serial.print(p.y);
    Serial.print("\tPressure = "); Serial.println(p.z);
    */
    
    if (p.y < (TS_MINY-5)) {
      Serial.println("erase");
      // press the bottom of the screen to erase 
      tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK);
    }
    // scale from 0->1023 to tft.width
    p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0);
    p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);
    /*
    Serial.print("("); Serial.print(p.x);
    Serial.print(", "); Serial.print(p.y);
    Serial.println(")");
    */
    if (p.y < BOXSIZE) {
       oldcolor = currentcolor;

       if (p.x < BOXSIZE) { 

         currentcolor = RED; 
         tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE);
       } else if (p.x < BOXSIZE*2) {
         currentcolor = YELLOW;
         tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE);
       } else if (p.x < BOXSIZE*3) {
         currentcolor = GREEN;
         tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, WHITE);
       } else if (p.x < BOXSIZE*4) {
         currentcolor = CYAN;
         tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, WHITE);
       } else if (p.x < BOXSIZE*5) {
         currentcolor = BLUE;
         tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, WHITE);
       } else if (p.x < BOXSIZE*6) {
         currentcolor = MAGENTA;
         tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, WHITE);
       }

       if (oldcolor != currentcolor) {

          if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED);
          if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW);
          if (oldcolor == GREEN) tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN);
          if (oldcolor == CYAN) tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN);
          if (oldcolor == BLUE) tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE);
          if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA);
       }
    }
    if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) {
      tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor);
    }
  }
}






TEST OK~

2017年1月19日 星期四

旋轉編碼器消除彈跳











/*
  RotaryEncoderInterrupt sketch
  2017-01-19 test OK
 */

const int encoderPinA = 2;
const int encoderPinB = 3;
int Pos, oldPos;
volatile int encoderPos = 0; // variables changed within interrupts are volatile

void setup(){
  pinMode(6, OUTPUT);  digitalWrite(6, LOW); //encoder Gnd
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  Serial.begin(115200);
  attachInterrupt(1, doEncoder, CHANGE); // encoder pin on interrupt 0 (pin 3)
 // attachInterrupt(0, doEncoder, FALLING); // encoder pin on interrupt 0 (pin 2)
}

void loop(){
  uint8_t oldSREG = SREG;
  cli();  Pos = encoderPos;  SREG = oldSREG;  if(Pos != oldPos)
  {
    Serial.println(Pos,DEC);    oldPos = Pos;
  }
  delay(10);
}


void doEncoder(){
  if (digitalRead(encoderPinA) == digitalRead(encoderPinB))
    encoderPos++;    // count up if both encoder pins are the same
  else
    encoderPos--;    //count down if pins are different
}



接著發現一個狀況~~
若需設定的值範圍很大時不就要轉很久 ...

利用轉動速度快慢(偵測脈波寬度)的方式來決定增量的值


/*
  RotaryEncoderInterrupt sketch
  2017-01-20 test OK
 */

const int encoderPinA = 2;
const int encoderPinB = 3;
int Pos, oldPos;
unsigned long duration;
volatile int encoderPos = 0; // variables changed within interrupts are volatile

void setup(){
  pinMode(6, OUTPUT);  digitalWrite(6, LOW); //encoder Gnd
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  Serial.begin(115200);
  attachInterrupt(1, doEncoder, CHANGE); // encoder pin on interrupt 0 (pin 3)
 // attachInterrupt(0, doEncoder, FALLING); // encoder pin on interrupt 0 (pin 2)
}

void loop(){
  uint8_t oldSREG = SREG;
  cli();  Pos = encoderPos;  SREG = oldSREG;  if(Pos != oldPos){
    Serial.print(Pos,DEC); 
    Serial.print(",   Pulse Width /nS :");
    Serial.println(duration,DEC); 
    oldPos = Pos;
  }
  delay(10);
  duration = pulseIn(encoderPinA, HIGH,100000);
}


void doEncoder(){
  if (digitalRead(encoderPinA) == digitalRead(encoderPinB)){
    if(duration == 0 || duration >= 35001)encoderPos++;
    if(duration >= 1 && duration <= 35000)encoderPos += 20;
    if(duration >= 1 && duration <= 10000)encoderPos += 80;
  }   
  else{
    if(duration == 0 || duration >= 35001)encoderPos--;
    if(duration >= 1 && duration <= 35000)encoderPos -= 20;
    if(duration >= 1 && duration <= 10000)encoderPos -= 80;
     }
}


 轉一格有 1個訊號
//2018-06-26 test OK 



volatile long posCount = 0;
unsigned long t = 0;

void setup() {
  Serial.begin(115200);
  // 當狀態下降時,代表旋轉編碼器被轉動了
  attachInterrupt(1, rotaryEncoderChanged, FALLING);  //INT 1 -> pin 3
  pinMode(3, INPUT_PULLUP); // 輸入模式並啟用內建上拉電阻
  pinMode(4, INPUT_PULLUP); 
  pinMode(5, INPUT_PULLUP); 
  Serial.println("count reset to 0");
}

long position  = -999;
word position1,newPos1;


void loop() {
//delay(500);  
if (posCount != position) {
 position = posCount;
 Serial.println(position);
}

  if(digitalRead(5) == LOW){ // 按下開關,歸零
     posCount = 0;  
     delay(300);
  }
}


void rotaryEncoderChanged(){ // when CLK_PIN is FALLING
//  unsigned long temp = millis();  // 去彈跳
//  if(temp - t < 20)               // 去彈跳
//    return;                       // 去彈跳
//  t = temp;                       // 去彈跳
  
  // DT_PIN的狀態代表正轉或逆轉
  posCount += digitalRead(4) == HIGH ? 1 : -1;
 // Serial.println(count);
}



可以不使用中斷的 Library  ->   https://github.com/PaulStoffregen/Encoder
轉一格有 4個訊號