일단계 파이썬 v1.0 (2020-DEC-10)

'프로그래밍언어.Lib > 파이썬' 카테고리의 다른 글

<일단계 파이썬> 교재  (0) 2021.12.11
pyfirmata 기초  (0) 2019.12.02
ipython 의 매직명령어들  (0) 2016.10.18
ipython 기본 사용법  (0) 2016.10.18
MicroPython 개발자의 IoT 발표 (pyCon2016)  (0) 2016.09.27
윈도7에서 ipython 설치하기  (0) 2016.01.07
Posted by 살레시오

댓글을 달아 주세요

// Advanced Microcontroller-based Audio Workshop
//
// http://www.pjrc.com/store/audio_tutorial_kit.html
// https://hackaday.io/project/8292-microcontroller-audio-workshop-had-supercon-2015
// 
// Part 1-3: First "Hello World" program, play a music file
//
// WAV files for this and other Tutorials are here:
// http://www.pjrc.com/teensy/td_libs_AudioDataFiles.html

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav7;     //xy=91,352.00000953674316
AudioPlaySdWav           playSdWav6;     //xy=102,307.00000953674316
AudioPlaySdWav           playSdWav5;     //xy=108,261.0000286102295
AudioPlaySdWav           playSdWav3;     //xy=111.00000381469727,148.00000381469727
AudioPlaySdWav           playSdWav4;     //xy=113.00000381469727,210.0000057220459
AudioPlaySdWav           playSdWav1;     //xy=114,43.000003814697266
AudioPlaySdWav           playSdWav2;     //xy=114,95.00000190734863
AudioMixer4              mixer1;         //xy=308.0000114440918,118.00000381469727
AudioMixer4              mixer2;         //xy=473.0000534057617,227.0000057220459
AudioOutputI2S           i2s1;           //xy=640.0000991821289,266.0000276565552
AudioConnection          patchCord1(playSdWav7, 0, mixer2, 3);
AudioConnection          patchCord2(playSdWav6, 0, mixer2, 2);
AudioConnection          patchCord3(playSdWav5, 0, mixer2, 1);
AudioConnection          patchCord4(playSdWav3, 0, mixer1, 2);
AudioConnection          patchCord5(playSdWav4, 0, mixer1, 3);
AudioConnection          patchCord6(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord7(playSdWav2, 0, mixer1, 1);
AudioConnection          patchCord8(mixer1, 0, mixer2, 0);
AudioConnection          patchCord9(mixer2, 0, i2s1, 0);
AudioConnection          patchCord10(mixer2, 0, i2s1, 1);
// GUItool: end automatically generated code

AudioControlSGTL5000     sgtl5000_1;


///* Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14
//*/

/*// Use these with the Teensy 4.1 onboard SD card
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used
//*/

/*
//file names of guitar strings(gs):
const char* gs6[] ={"g600E.wav","g601F.wav","g602F#.wav","g603G.wav","g604G#.wav","g605A.wav","g606A#.wav","g607B.wav","g608C.wav","g609C#.wav","g610D.wav","g611D#.wav"};
const char* gs5[] ={"g500A.wav","g501A#.wav","g502B.wav","g503C.wav","g504C#.wav","g505D.wav","g506D#.wav","g507E.wav","g508F.wav","g509F#.wav"};
const char* gs4[] ={"g400D.wav","g401D#.wav","g402E.wav","g403F.wav","g404F#.wav","g405G.wav","g406G#.wav","g407A.wav","g408A#.wav","g409B.wav"};
const char* gs3[] ={"g300G.wav","g301G#.wav","g302A.wav","g303A#.wav","g304B.wav","g305C.wav","g306C#.wav","g307D.wav","g308D#.wav","g309E.wav"};
const char* gs2[] ={"g200B.wav","g201C.wav","g202C#.wav","g203D.wav","g204D#.wav","g205E.wav","g206F.wav","g207F#.wav","g208G.wav","g209G#.wav"};
const char* gs1[] ={"g100E.wav","g101F.wav","g102F#.wav","g103G.wav","g104G#.wav","g105A.wav","g106A#.wav","g107B.wav","g108C.wav","g109C#.wav"};
//C:C,E,G:{8,7,5,5,5,3}
//F:F,A,C:{1,0,3,2,1,1}
//*/

const char* gstr[] ={
 "g600E.wav"/*0*/,"g601F.wav"/*1*/,"g602F#.wav"/*2*/,"g603G.wav"/*3*/,"g604G#.wav"/*4*/
,"g500A.wav"/*5*/,"g501A#.wav"/*6*/,"g502B.wav"/*7*/,"g503C.wav"/*8*/,"g504C#.wav"/*9*/
,"g400D.wav"/*10*/,"g401D#.wav"/*11*/,"g402E.wav"/*12*/,"g403F.wav"/*13*/,"g404F#.wav"/*14*/
,"g300G.wav"/*15*/,"g301G#.wav"/*16*/,"g302A.wav"/*17*/,"g303A#.wav"/*18*/                
,"g200B.wav"/*19*/,"g201C.wav"/*20*/,"g202C#.wav"/*21*/,"g203D.wav"/*22*/,"g204D#.wav"/*23*/
,"g100E.wav"/*24*/,"g101F.wav"/*25*/,"g102F#.wav"/*26*/,"g103G.wav"/*27*/,"g104G#.wav"/*28*/
//아래는 1번 줄의 고음을 sampling한 것들
,"g105A.wav"/*29*/,"g106A#.wav"/*30*/,"g107B.wav"/*31*/,"g108C.wav"/*32*/,"g109C#.wav"/*33*/
,"g110D.wav"/*34*/,"g111D#.wav"/*35*/,"g112E.wav"/*36*/,"g113F.wav"/*37*/,"g114F#.wav"/*38*/,"g115G.wav"/*39*/
,"g116G#.wav"/*40*/,"g117A.wav"/*41*/,"g118A#.wav"/*42*/,"g119B.wav"/*43*/
};

//C:C,E,G:{8(C),0(E),3(G),12(E),15(G),20(C)}
//F:F,A,C:{1(F),5(A),8(C),13(F),17(A),20(C)}

//주의: 13번핀(LED)는 다른 용도(SCK)로 예약되어 있으므로 사용하면 안됨!
void setup() {
  
  Serial.begin(9600);
  
  // AudioMemoryUsageMax() 함수로 조사한 것보다 커야 한다
  // 이 예제의 경우에 7값이 찍혔다
  // https://www.pjrc.com/teensy/td_libs_AudioConnection.html
  AudioMemory(50);
  
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.7);
  
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      while(1);
    }
  }

  
  delay(1000);

/*
  mixer1.gain(0, 0.5);
  mixer1.gain(1, 0.5);
  mixer1.gain(2, 0.5);
  mixer1.gain(3, 0.5);
  mixer2.gain(0, 0.5);
  mixer2.gain(1, 0.5);
  mixer2.gain(2, 0.5);
  */
}

#define DELAY 2
void loop() {
  //if (playSdWav1.isPlaying() == false) {
  
    Serial.println(AudioMemoryUsageMax());
/*
    playChord(8,0,3,12,15,20);// playChord(8,0,15,24,32,39);
    delay(random(5,10)*40); // wait for library to parse WAV info
    playChord(8,0,3,12,15,20);// playChord(8,0,15,24,32,39);
    delay(random(5,10)*40); // wait for library to parse WAV info
    playChord(8,24,27,32,36,39);//playChord(8,3,12,20,27,36);
    delay(random(5,10)*40); // wait for library to parse WAV info
    playChord(8,24,27,32,36,39);//playChord(8,3,12,20,27,36);
    delay(random(5,10)*40); // wait for library to parse WAV info
*/
    playChord(8,0,15,24,32,39);
    delay(random(5,10)*10); // wait for library to parse WAV info
    playChord(8,0,15,24,32,39);
    delay(random(5,10)*10); // wait for library to parse WAV info
    playChord(8,3,12,20,27,36);
    delay(random(5,10)*10); // wait for library to parse WAV info
    playChord(8,3,12,20,27,36);
    delay(random(5,10)*10); // wait for library to parse WAV info
  
  // do nothing while playing...
}

void playChord(byte s1, byte s2, byte s3, byte s4, byte s5, byte s6){
  
    playSdWav1.stop();//must be stopped first
    do {
      playSdWav1.play(gstr[s1]);
      delay(DELAY);
    } while (!playSdWav1.isPlaying());
    
    playSdWav2.stop();//must be stopped first
    do{
      playSdWav2.play(gstr[s2]);
      delay(DELAY);
    } while (!playSdWav2.isPlaying());
    
    playSdWav3.stop();//must be stopped first
    do {
      playSdWav3.play(gstr[s3]);
      delay(DELAY);
    } while (!playSdWav3.isPlaying());
    
    playSdWav4.stop();//must be stopped first
    do {playSdWav4.play(gstr[s4]);
    delay(DELAY);} while (!playSdWav4.isPlaying());
    
    playSdWav5.stop();//must be stopped first
    do {playSdWav5.play(gstr[s5]);
    delay(DELAY);} while (!playSdWav5.isPlaying());
    
    playSdWav6.stop();//must be stopped first
    do {playSdWav6.play(gstr[s6]);
    delay(DELAY);} while (!playSdWav6.isPlaying());
}

Posted by 살레시오

댓글을 달아 주세요

teensy audio design GUI

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav3;     //xy=74,367
AudioPlaySdWav           playSdWav1;     //xy=77,241
AudioPlaySdWav           playSdWav7;     //xy=78,597
AudioPlaySdWav           playSdWav4;     //xy=80,425
AudioPlaySdWav           playSdWav2;     //xy=81,303
AudioPlaySdWav           playSdWav6;     //xy=82,535
AudioPlaySdWav           playSdWav5;     //xy=86,476
AudioMixer4              mixer1;         //xy=291,316
AudioMixer4              mixer2;         //xy=449,424
AudioOutputI2S           i2s1;           //xy=626,430
AudioConnection          patchCord1(playSdWav3, 0, mixer1, 2);
AudioConnection          patchCord2(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord3(playSdWav7, 0, mixer2, 3);
AudioConnection          patchCord4(playSdWav4, 0, mixer1, 3);
AudioConnection          patchCord5(playSdWav2, 0, mixer1, 1);
AudioConnection          patchCord6(playSdWav6, 0, mixer2, 2);
AudioConnection          patchCord7(playSdWav5, 0, mixer2, 1);
AudioConnection          patchCord8(mixer1, 0, mixer2, 0);
AudioConnection          patchCord9(mixer2, 0, i2s1, 0);
AudioConnection          patchCord10(mixer2, 0, i2s1, 1);
// GUItool: end automatically generated code

AudioControlSGTL5000     sgtl5000_1;

// 오디오보드의 sd카드 슬롯을 이용
//#define SDCARD_CS_PIN    10
//#define SDCARD_MOSI_PIN  7
//#define SDCARD_SCK_PIN   14

// Teensy4.1보드의 sd카드 슬롯을 이용
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used


//기타와 관련된 상수들
#define TOUCHED 1
#define UNTOUCHED 0

#define STRING1 24
#define STRING2 25
#define STRING3 26
#define STRING4 27
#define STRING5 28
#define STRING6 29


void setup() {
  Serial.begin(115200);
  delay(1000);

  // put your setup code here, to run once:
  AudioMemory(8);
  sgtl5000_1.enable();
  sgtl5000_1.volume(1.0);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);

 
  if (!(SD.begin(SDCARD_CS_PIN))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  
  
  Serial.println("Ready.");
  
  pinMode(STRING1,INPUT);
  pinMode(STRING2,INPUT);
  pinMode(STRING3,INPUT);
  pinMode(STRING4,INPUT);
  pinMode(STRING5,INPUT);
  pinMode(STRING6,INPUT);
  
}


bool prevString1 = UNTOUCHED;
bool prevString2 = UNTOUCHED;
bool prevString3 = UNTOUCHED;
bool prevString4 = UNTOUCHED;
bool prevString5 = UNTOUCHED;
bool prevString6 = UNTOUCHED;

///*
#define TIME_WAIT_TO_PLAY 2
void forcePlay(AudioPlaySdWav *ptrPlaySdWav, const char *wav){
  ptrPlaySdWav->stop();
  do{
    ptrPlaySdWav->play(wav);
    delay(TIME_WAIT_TO_PLAY);
  } while(!ptrPlaySdWav->isPlaying());
}
//*/

void loop() {

  int tm=millis();
///*
  bool str1 = digitalRead(STRING1);
  if (prevString1==UNTOUCHED and str1==TOUCHED){
    forcePlay(&playSdWav1, "g100E.wav");
  }

  bool str2 = digitalRead(STRING2);
  if (prevString2==UNTOUCHED and str2==TOUCHED){
    forcePlay(&playSdWav2, "g200B.wav");
  }

  bool str3 = digitalRead(STRING3);
  if (prevString3==UNTOUCHED and str3==TOUCHED){
    forcePlay(&playSdWav3, "g300G.wav");
  }

  bool str4 = digitalRead(STRING4);
  if (prevString4==UNTOUCHED and str4==TOUCHED){
    forcePlay(&playSdWav4, "g400D.wav");
  }


  bool str5 = digitalRead(STRING5);
  if (prevString5==UNTOUCHED and str5==TOUCHED){
    forcePlay(&playSdWav5, "g500A.wav");
  }

  bool str6 = digitalRead(STRING6);
  if (prevString6==UNTOUCHED and str6==TOUCHED){
    forcePlay(&playSdWav6, "g600E.wav");
  }

  
  prevString1=str1;
  prevString2=str2;
  prevString3=str3;
  prevString4=str4;
  prevString5=str5;
  prevString6=str6;
//*/
  

/*
  playSdWav1.stop();
  do{
    playSdWav1.play("g600E.wav");
    delay(TIME_WAIT_TO_PLAY);
  } while(!playSdWav1.isPlaying());
*/
  
  Serial.print(millis()-tm);
  Serial.print(", S1:");Serial.print(str1);
  Serial.print(", S2:");Serial.print(str2);
  Serial.print(", S3:");Serial.print(str3);
  Serial.print(", S4:");Serial.print(str4);
  Serial.print(", S5:");Serial.print(str5);
  Serial.print(", S6:");Serial.print(str6);
  Serial.println();
  delay(10);
}

Posted by 살레시오

댓글을 달아 주세요

// 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 살레시오

댓글을 달아 주세요

FreeCAD의 스케치는 선분이나 사각형의 중심점을 자동으로 생성해 주지 않는다. (0.18버전 기준) 하지만 대칭구속기능을 이용하면 선분/사각형의 중심점을 쉽게 생성할 수 있다.  먼저 선분 주위 아무데나 점을 찍는다. 그리고 아래 그림과 같은 순서대로 점들을 선택한다.

 

(1)(2) 선분의 두 끝점을 차례로 선택

(2) (방금 생성한) 선분 밖의 점을 선택

(3) 대칭 구속조건 버튼 클릭

 

 

그러면 다음과 같이 중심점으로 설정된다.

 

 

사각형의 중심점도 비슷하게 생성할 수 있다. 먼저 사각형 내부에 점을 아무데나 찍는다. 이후에 다음과 같은 순서로 점을 선택한 후 구속조건 버튼을 누른다.

 

(1)(2) 사각형의 두 마주보는 꼭지점을 차례로 선택

(3) 방금 찍은 (사각형 내부의) 점을 선택

(4) 대칭구속버튼 클릭

 

 

그러면 아래와 같이 생성한 점이 사각형의 중심점이 된다.

 

 

이후에는 이 중심점을 끌어서 사각형의 위치를 조절할 수도 있다.

 

[gdoc]

 

Posted by 살레시오

댓글을 달아 주세요

  FreeCAD의 마커(marker)는 스케치상에 존재하는 특징점을 칭한다. 예를 들면 사각형의 꼭지점, 좌표상의 원점, 원의 중심점 같은 것들이다. 그것의 크기가 초기 설정으로는 너무 작아서 작업하기에 불편하다. 크기를 키우려면 

 

편집>환경설정 메뉴

 

로 들어가서 아래와 같이 Display탭의 Marker size를 조절하면 된다. 13px 이상으로 설정해 놓으면 작업하기 편하다.

 

 

바로 적용이 안 되는 것 같다.(0.18버전) 사이즈를 설정한 후 freecad를 재시작해야 새로운 크기값이 적용된다.

 

[gdoc]

 

Posted by 살레시오

댓글을 달아 주세요

위와 같이 생긴 저가(1.5$정도)의 mp3 모듈을 사용해 보았다.

(a) 장점 : 저가,  4MByte 플래시롬 내장(pc에서 usb로 연결해서 mp3파일 복사), 앰프내장으로 스피커에 바로 연결 가능, 다양한 외부 트리거(최대 255곡까지 선택연주 가능), 아두이노로 Serial 제어하는 라이브러리 존재

(b) 단점 : 플래시롬의 용량이 다소 아쉽다. 트리거 신호 이후 mp3파일가 시작되는 delay가 생각보다 크다(느낌상 0.3초 정도) 이 단점들 때문에 내가 진행하는 프로젝트에서는 사용이 불가했다.

(c) 주의점 : 입력 전압은 5V이지만 내부 동작전압은 3.3V이므로 5V로 동작하는 아두이노와 결선할 때는 주의가 필요함. 예를 들어 Serial모드로 제어할 때는 전압레벨 변환기를 통하든가 아니면 적어도 아래와 같이 저항을 통해서 결선해야 한다.

위의 가이드대로 저항을 통해서 연결하지 않고 그냥 직결하면 이 보드가 손상될 가능성이 크다. 

Posted by 살레시오

댓글을 달아 주세요

ESP32보드를 아두이노 IDE에서 C++   로 코딩할 수 있는 데 매우 간단하게 세팅할 수 있다.

(1) 아두이노 IDE에서 [파일]>[환경설정] 창의 "추가적인 보드 매니저 URLs"에 아래 주소를 붙여넣기(ctrl+v)로 추가하고 [확인]버튼을 누른다.

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 

(2) 위 과정이 끝났다면 [툴]>[보드]>[보드 매니저] 창의 검색칸에 ESP32라고 입력하면 보드매니저를 설치할 수 있다. (현재 1.0.4 버전)

(3) 이제 esp32보드를 선택할 수 있다. 통신 포트(serial port)도 맞게 설정한다.



위의 과정을 다 했다면 이제 ESP32보드를 아두이노IDE로 코딩할 수 있다. WeMos LOLIN32 보드의 테스트 LED를 블링킹하려면 다음과 같이 코딩하고 업로드 버튼을 클릭한다.

void setup() {

    pinMode(5,OUTPUT);

}

 void loop() {

    digitalWrite(5,HIGH);

    delay(500);

    digitalWrite(5,LOW);

    delay(500);    

}


참고로 유튜브 관련 영상에 보면 컴파일이 끝나면 BOOT(gpio0)핀이 LOW가 되어야 업로드가 된다고 하는데.. 현재 최신 버전의 esp32매니저와 적어도 LOLIN32 보드에서는 그렇지 않고 자동으로 업로딩되고 업로딩 완료시 리셋까지 되는 것 같다.

Posted by 살레시오

댓글을 달아 주세요