// 2021/11/8: Lolin32+OLED final

//#define DEBUG_SERIAL

#include <WiFi.h>
#include <driver/adc.h> // for adc_power_off()


#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 oled(128, 64, &Wire, -1);

// 한 번만 샘플링하면 1~2%의 확률로 0에 가까운 값이 읽힌다고 한다(잡음)
// 따라서 여러번 샘플링하여 평균값으로 판단하는 것이 안정적이다.
// SAMPLES가 20이면 loop()함수 한 번 실행 시간이 76ms 정도이다.
// 30이면 113ms 정도이다.
#define SAMPLES 20


// touchRead() 평균값이 아래 문턱값 이하이면 터치된 걸로 판단
#define THRESHOLD 20


#define PAD1    36 //(1) C#
#define PAD2    39 //(2) C
#define PAD3    34 //(3) D#
#define PAD4    35 //(4) D
#define PAD5    25 //(5) E
#define PAD6    26 //(6) F#
#define PAD7    19 //(7) F
#define PAD8    23 //(8) G#
#define PAD9    18 //(9) G
#define TPAD10  T9 //(10)A#
#define TPAD11  T8 //(11)A
#define TPAD12  T7 //(12)B
#define TPAD13  T6 //(13)
#define TPAD14  T5 //(14)
#define TPAD15  T4 //(15)

#define OUT_1  5
#define OUT_2  17
#define OUT_3  16
#define OUT_4  4
#define OUT_A  0
#define OUT_B  2
#define OUT_C  15

void setup() {

  // 소모전력을 줄이기 위해서 WiFi와 bt는 끈다.
  // ADC도 사용하지 않으므로 꺼야 한다.
  adc_power_off();
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  btStop();

  // put your setup code here, to run once:
  
  ///*
  pinMode(PAD1, INPUT);
  pinMode(PAD2, INPUT);
  pinMode(PAD3, INPUT);
  pinMode(PAD4, INPUT);
  pinMode(PAD5, INPUT);
  pinMode(PAD6, INPUT);
  pinMode(PAD7, INPUT);
  pinMode(PAD8, INPUT);
  pinMode(PAD9, INPUT);
  
  pinMode(OUT_1, OUTPUT); //LED_BUILTIN
  pinMode(OUT_2, OUTPUT);
  pinMode(OUT_3, OUTPUT);
  pinMode(OUT_4, OUTPUT);
  pinMode(OUT_A, OUTPUT);
  pinMode(OUT_B, OUTPUT);
  pinMode(OUT_C, OUTPUT);

  // Address 0x3D for 128x64
  boolean isDisplayReady = oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);

#ifdef DEBUG_SERIAL //#######################
  Serial.begin(115200);
  delay(100);
  if(!isDisplayReady) { 
    Serial.println(F("OLED(SSD1306) diaplay detection failed"));
  }
#endif //####################################

  oled.clearDisplay();
  oled.display();
}


byte getTouchAverage(byte tN){
  int totalRead = 0;
  for(byte n=0; n<SAMPLES; n++){
    totalRead += touchRead(tN);
  }
  return totalRead/SAMPLES;
}

char notes[] = {' ', 'C', 'D', 'E', 'F', 'G', 'A', 'B'};
char *chords[] = {
    "",  //CBA:000
    "7", //CBA:001
    "m", //CBA:010
    "m7",//CBA:011
    "M", //CBA:100
    "M7",//CBA:101
    "sus4", //CBA:110
    "dim7", //CBA:111
};
byte idNote=0;
boolean isHalfHigh=false;
byte idChord=0;
byte prevChordByte=0;



void loop() {

  
#ifdef DEBUG_SERIAL //#######################
  int tm = millis();//(2)
#endif //####################################

  byte chordByte;

  boolean p1=digitalRead(PAD1);
  boolean p2=digitalRead(PAD2);
  boolean p3=digitalRead(PAD3);
  boolean p4=digitalRead(PAD4);
  boolean p5=digitalRead(PAD5);
  boolean p6=digitalRead(PAD6);
  boolean p7=digitalRead(PAD7);
  boolean p8=digitalRead(PAD8);
  boolean p9=digitalRead(PAD9);

  byte tp10=getTouchAverage(TPAD10);
  byte tp11=getTouchAverage(TPAD11);
  byte tp12=getTouchAverage(TPAD12);
  byte tp13=getTouchAverage(TPAD13);
  byte tp14=getTouchAverage(TPAD14);
  byte tp15=getTouchAverage(TPAD15);
  
  boolean p10 = tp10 < THRESHOLD;
  boolean p11 = tp11 < THRESHOLD;
  boolean p12 = tp12 < THRESHOLD;
  boolean p13 = tp13 < THRESHOLD;
  boolean p14 = tp14 < THRESHOLD;
  boolean p15 = tp15 < THRESHOLD;


  if(p1==HIGH){ //C#
    
    digitalWrite(OUT_1, 1);
    digitalWrite(OUT_2, 0);
    digitalWrite(OUT_3, 0);
    digitalWrite(OUT_4, 0);
    digitalWrite(OUT_A, p4); //gpio0
    digitalWrite(OUT_B, p5);
    digitalWrite(OUT_C, p7);   

    idNote=1;
    isHalfHigh = true; 
    idChord = p4+p5*2+p7*4;

    chordByte = 1+idChord*16;
    
  } else if (p2==HIGH){ //C
    
    digitalWrite(OUT_1, 0);
    digitalWrite(OUT_2, 1);
    digitalWrite(OUT_3, 0);
    digitalWrite(OUT_4, 0);
    digitalWrite(OUT_A, p4); //gpio0
    digitalWrite(OUT_B, p5);
    digitalWrite(OUT_C, p7);  

    idNote=1;
    isHalfHigh = false; 
    idChord = p4+p5*2+p7*4;

    chordByte = 2+idChord*16;

  } else if (p3==HIGH){ //D#

    digitalWrite(OUT_1, 1);
    digitalWrite(OUT_2, 1);
    digitalWrite(OUT_3, 0);
    digitalWrite(OUT_4, 0);
    digitalWrite(OUT_A, p5); //gpio0
    digitalWrite(OUT_B, p7);
    digitalWrite(OUT_C, p9);  

    idNote=2;
    isHalfHigh = true; 
    idChord = p5+p7*2+p9*4;

    chordByte = 3+idChord*16;

  } else if (p4==HIGH){ //D

    digitalWrite(OUT_1, 0);
    digitalWrite(OUT_2, 0);
    digitalWrite(OUT_3, 1);
    digitalWrite(OUT_4, 0);
    digitalWrite(OUT_A, p5); //gpio0
    digitalWrite(OUT_B, p7);
    digitalWrite(OUT_C, p9);  

    idNote=2;
    isHalfHigh = false; 
    idChord = p5+p7*2+p9*4;

    chordByte = 4+idChord*16;

  } else if (p5==HIGH){ //E

    digitalWrite(OUT_1, 1);
    digitalWrite(OUT_2, 0);
    digitalWrite(OUT_3, 1);
    digitalWrite(OUT_4, 0);
    digitalWrite(OUT_A, p7); //gpio0
    digitalWrite(OUT_B, p9);
    digitalWrite(OUT_C, p11);  

    idNote=3;
    isHalfHigh = false; 
    idChord = p7+p9*2+p11*4;

    chordByte = 5+idChord*16;
    
  } else if (p6==HIGH){ //F#

    digitalWrite(OUT_1, 0);
    digitalWrite(OUT_2, 1);
    digitalWrite(OUT_3, 1);
    digitalWrite(OUT_4, 0);
    digitalWrite(OUT_A, p9); //gpio0
    digitalWrite(OUT_B, p11);
    digitalWrite(OUT_C, p12);

    idNote=4;
    isHalfHigh = true; 
    idChord = p9 + p11*2 + p12*4;

    chordByte = 6+idChord*16;

  } else if (p7==HIGH){ //F

    digitalWrite(OUT_1, 1);
    digitalWrite(OUT_2, 1);
    digitalWrite(OUT_3, 1);
    digitalWrite(OUT_4, 0);
    digitalWrite(OUT_A, p9); //gpio0
    digitalWrite(OUT_B, p11);
    digitalWrite(OUT_C, p12);  

    idNote=4;
    isHalfHigh = false; 
    idChord = p9+p11*2+p12*4;

    chordByte = 7+idChord*16;


  } else if (p8==HIGH){ //G#

    digitalWrite(OUT_1, 0);
    digitalWrite(OUT_2, 0);
    digitalWrite(OUT_3, 0);
    digitalWrite(OUT_4, 1);
    digitalWrite(OUT_A, p11); //gpio0
    digitalWrite(OUT_B, p12);
    digitalWrite(OUT_C, p13);  

    idNote=5;
    isHalfHigh = true; 
    idChord = p11 + p12*2 + p13*4;

    chordByte = 8+idChord*16;

  } else if (p9==HIGH){ //G

    digitalWrite(OUT_1, 1);
    digitalWrite(OUT_2, 0);
    digitalWrite(OUT_3, 0);
    digitalWrite(OUT_4, 1);
    digitalWrite(OUT_A, p11); //gpio0
    digitalWrite(OUT_B, p12);
    digitalWrite(OUT_C, p13);  

    idNote=5;
    isHalfHigh = false; 
    idChord = p11 + p12*2 + p13*4;

    chordByte = 9+idChord*16;

  } else if (p10==HIGH){ //A#

    digitalWrite(OUT_1, 0);
    digitalWrite(OUT_2, 1);
    digitalWrite(OUT_3, 0);
    digitalWrite(OUT_4, 1);
    digitalWrite(OUT_A, p12); //gpio0
    digitalWrite(OUT_B, p13);
    digitalWrite(OUT_C, p14);  

    idNote=6;
    isHalfHigh = true; 
    idChord = p12 + p13*2 + p14*4;

    chordByte = 10+idChord*16;

  } else if (p11==HIGH){ //A

    digitalWrite(OUT_1, 1);
    digitalWrite(OUT_2, 1);
    digitalWrite(OUT_3, 0);
    digitalWrite(OUT_4, 1);
    digitalWrite(OUT_A, p12); //gpio0
    digitalWrite(OUT_B, p13);
    digitalWrite(OUT_C, p14);  

    idNote=6;
    isHalfHigh = false; 
    idChord = p12 + p13*2 + p14*4;

    chordByte = 11+idChord*16;

  } else if (p12==HIGH){ //B

    digitalWrite(OUT_1, 0);
    digitalWrite(OUT_2, 0);
    digitalWrite(OUT_3, 1);
    digitalWrite(OUT_4, 1);
    digitalWrite(OUT_A, p13); //gpio0
    digitalWrite(OUT_B, p14);
    digitalWrite(OUT_C, p15);  

    idNote=7;
    isHalfHigh = false; 
    idChord = p13 + p14*2 + p15*4;

    chordByte = 12+idChord*16;

  } else { //아무 코드도 짚지 않았을 때
  
    digitalWrite(OUT_1, 0);
    digitalWrite(OUT_2, 0);
    digitalWrite(OUT_3, 0);
    digitalWrite(OUT_4, 0);
    digitalWrite(OUT_A, 0);
    digitalWrite(OUT_B, 0);
    digitalWrite(OUT_C, 0);      

    idNote=0;
    isHalfHigh = false; 
    idChord = 0;

    chordByte = 0;
  }


  // 만약 oled가 갱신된다면 87ms 가 소요되고
  // 갱신되지 않는다면 58ms가 소요된다.
  // (OLED에 코드를 새로 표시하는데 30ms정도가 소요됨)
  
  if (chordByte != prevChordByte) {

    oled.clearDisplay();
    oled.setTextColor(WHITE);
    if (idNote>0) {
      oled.setCursor(0, 5);
      oled.setTextSize(8);
      oled.print( notes[idNote] );
    }
    if (isHalfHigh){
      oled.setCursor(48, 0);
      oled.setTextSize(4);
      oled.print("#");
    }
    if (idChord>0){
      oled.setCursor(48, 32);
      oled.setTextSize(4);
      oled.print( chords[idChord] );
    }
    oled.display(); //display the text on the screen


    prevChordByte = chordByte;
  }


#ifdef DEBUG_SERIAL
  Serial.print(millis()-tm);//(3)소요 시간 표시
  Serial.print("ms per 1 loop :");Serial.print(p1);
  Serial.print(':');Serial.print(p2);
  Serial.print(':');Serial.print(p3);
  Serial.print(':');Serial.print(p4);
  Serial.print(':');Serial.print(p5);
  Serial.print(':');Serial.print(p6);
  Serial.print(':');Serial.print(p7);
  Serial.print(':');Serial.print(p8);
  Serial.print(':');Serial.print(p9);
  Serial.print(':');Serial.print(tp10);
  Serial.print(':');Serial.print(tp11);
  Serial.print(':');Serial.print(tp12);
  Serial.print(':');Serial.print(tp13);
  Serial.print(':');Serial.print(tp14);
  Serial.print(':');Serial.print(tp15);
  Serial.println();
#endif


}

Posted by 살레시오

댓글을 달아 주세요

//2021년10월29일:Wemos LOLIN32 Lite 보드 실험

#include <WiFi.h>
#include <driver/adc.h> // for adc_power_off()

// 터치입력핀(8개)과 출력핀번호(8개)를 저장한 배열들
// gpio22핀은 내부적으로 LED에 연결되어 LOW 값에 켜진다.(역동작)
// gpio22핀을 출력핀으로 사용하는 데에는 문제가 없다.
byte inTouch[8] ={T0, T2, T3, T4, T5, T6, T7, T8};
byte outPin[8] = {22, 19, 23, 18, 17, 16, 26, 25};


// 한 번만 샘플링하면 1~2%의 확률로 0에 가까운 값이 읽히는 것 같다.
// 따라서 여러번 샘플링하여 평균값으로 판단하는 것이 안정적이다.
// SAMPLES가 20이면 loop()함수 한 번 실행 시간이 76ms 정도이다.
// 30이면 113ms 정도이다.
#define SAMPLES 20


// touchRead() 평균값이 아래 문턱값 이하이면 터치된 걸로 판단
#define THRESHOLD 20


void setup() {
  
  // 소모전력을 줄이기 위해서 WiFi와 bt는 끈다.
  // ADC도 사용하지 않으므로 꺼야 한다.
  adc_power_off();
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  btStop();
    
  // 출력핀들을 OUTPUT으로 설정한다.
  for(byte k=0;k<8;k++){
    pinMode(outPin[k], OUTPUT);
  }

  //아래의 (1),(2),(3)은 소요시간을 확인하기 위한 코드
  //Serial.begin(115200); delay(100);//(1)
}


void loop() {
  //int tm = millis();//(2)

  for(byte k=0;k<8;k++) {
    int totalRead = 0;
    for(byte n=0; n<SAMPLES; n++) {
      totalRead += touchRead(inTouch[k]);
    }
    int averageRead = totalRead/SAMPLES;
    digitalWrite(outPin[k], averageRead<THRESHOLD);
  }

  //Serial.println(millis()-tm);//(3)소요 시간 표시
}

Posted by 살레시오

댓글을 달아 주세요

FreeCAD에서 스케치에 있는 치수(dimension)에 이름을 붙여서 다른 곳에서 재사용할 수 있다. 치수를 입력하는 창에 숫자값을 입력하는 칸 바로 맡에 이름을 기입하는 곳이 있는데 이곳에 이름을 기입하면 그 숫자값을 다른곳에서도 참조할 수 있다.

 

 

예를 들어 Sketch001 이라는 스케치 내에서 어떤 치수에 length 라는 이름을 주었다면 그 치수는 다음과 같은 이른으로 참조할 수 있다.

 

Sketch001.Constraints.length

 

중간에 Constraints 라는 이름을 거쳐야 사용할 수 있다는 점에 유의해야 한다. 치수를 입력하는 창에서 숫자 대신 '='키를 누르면 수식편집기 창이 뜨고 거기에 수식을 입력할 수 있다.

 

 

아예 spreadsheet를 하나 생성하고 거기에서 부품에 관련된 치수들에 이름을 붙여서 관리할 수도 있다. workbench에서 spreadsheet를 선택하면 부품에 Spreadsheet를 하나 생성할 수 있다.

 

 

Spreadsheet의 이름을 편의상 Var라고 변경했다. 이후에 한 셀에 11이라는 숫자를 기입하고 그 셀에서 마우스 우클릭을 하면 뜨는 셀 속성 창의 맨 오른쪽 탭인 별칭(A)을 선택하면 아래 그림과 같이 셀의 별칭을 입력할 수 있다.

 

 

이렇게 해 놓으면 이 셀의 수치는 다음과 같이 참조할 수 있고

 

Var.length

 

이 참조는 부품의 치수를 기입하는 어떤 창에서든 사용할 수 있다.

 

이렇게 추후에 변경될 가능성이 높은 치수들을 Spreadsheet로 관리하면 나중에 부품의 변경을 훨씬 용이하게 할 수 있다.

 

[gdoc]

 

Posted by 살레시오

댓글을 달아 주세요