산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

Arduino 다중 스레드 방법(프로토스레딩 자습서)

구성품 및 소모품

Arduino UNO
× 1
Sunfounder Blue 16x2 액정 디스플레이(LCD)
× 1
브레드보드(일반)
물론 전선도 있습니다.
× 1
회전 전위차계(일반)
저항 등급이 확실하지 않습니다. 아마도 1Kohm일 것입니다.
× 1

이 프로젝트 정보

이 비디오는 단일 코어 arduino가 한 번에 3가지 작업을 수행하도록 유도하여 신진 프로토타입 경력 동안 하고 싶었을 수 있는 일을 보여줍니다. 이 경우 우리는:

<울>
  • 중단 없이 일정한 속도로 백라이트를 깜박임
  • <울>
  • 매초마다 정수를 증가시키고 중단 없이 디스플레이에 쓰기
  • <울>
  • 몇 초마다 몇 개의 메시지를 순환하고 중단 없이 디스플레이에 쓰기
  • 제목을 보셨군요!

    프로토스레딩은 Arduino에서 일반적으로 멀티태스킹 작업(두 개 이상의 작업을 한 번에 또는 다른 간격으로 수행)을 수행하는 방법입니다. . 즉, "다중 스레드"입니다! 하지만 Sparky, Arduino는 절차 코드가 있는 단일 코어 칩이므로 진정한 멀티스레딩은 불가능합니다. 그런데 왜? 프로토스레딩은 어떻게 다른가요?

    "실제" 멀티스레딩 대 프로토스레딩

    프로토스레딩을 이해하려면 제대로, 우리는 먼저 그것이 실제로 멀티스레딩이 아닌 이유를 이해해야 합니다.

    인텔이 펜티엄 프로세서에서 이 새로운 "하이퍼스레딩"을 판매했을 때를 기억하십니까? 아니? 아직 태어나지 않았습니까? 그럼 역사 수업을 할 시간이야, 얘야! 하이퍼스레딩은 Intel이 프로세서의 단일 코어를 2개의 코어인 것처럼 "작동"하거나 2개의 코어가 4개의 코어인 것처럼 "작동"하도록 하는 기술입니다. 하지만 왜 이것이 Arduino와 관련이 있습니까? 답은 주기입니다.

    마이크로컨트롤러와 CPU는 모두 "주기"로 작동합니다. 얼마나 빨리 하느냐(초에 몇 번)가 클럭 속도입니다. CPU의 Ghz 등급을 보았고 이것이 얼마나 빠른지와 관련이 있다는 것을 알고 있을 것입니다. Ghz는 많을수록 좋죠? 하지만 왜? 이것이 프로세서가 달성할 수 있는 초당 사이클 수이기 때문입니다(과열 및 화재 없이 - 정말!).

    데이터시트에 관심이 없다면 Arduino Uno의 마이크로프로세서 칩인 Atmel ATMega328P가 기본적으로 16Mhz에서 실행된다는 것을 알 수 있습니다. 20Mhz가 가능하지만 메모리에 데이터를 쓰는 것과 같은 일을 엉망으로 만들지 않도록 전화를 겁니다. 16Mhz는 1초마다 Arduino가 16,000,000주기를 처리하고 있다는 것을 의미합니다. 일명 1600만 작업을 수행합니다. 자, 이것들은 코드 라인이 아닙니다. 그것은 엄청나게 빠르며 Arduino는 상대적으로 느립니다. 레지스터 안팎으로 데이터를 이동하는 것과 같은 프로세서 명령입니다. 이 개요보다 낮은 수준으로 이동하는 것은 상당히 기술적인 일이므로 독자에게 연습 문제로 남겨 두겠지만 이것이 요지입니다. :)

    따라서 사용 가능한 최고의 칩에 불이 붙기 전에 코어에서 너무 빨리 갈 수 있다면 영원히 그 속도로 갇히게 되는 것입니까? 그것이 우리가 할 수 있는 가장 빠른 일입니까? 그것이 밝혀진 바와 같이, 아닙니다! 멀티코어 CPU 및 멀티스레딩을 입력합니다. 컴퓨터 CPU에서 다중 스레드 응용 프로그램은 CPU의 다른 코어에서 서로 병렬로 작동하는 두 개의 개별 프로세스입니다. 이러한 프로세스는 작업을 함께 완료하기 위해 상호 작용하지만 가정할 수 있는 것처럼 작업을 균등하게 분할할 필요는 없습니다. 일반적으로 다른 스레드의 관리자 역할을 하는 메인 프로세스/"스레드"가 있으며, 그 다음에는 각각이 특정 작업을 수행할 수 있는 하나 이상의 작업자 스레드가 관리합니다. 좋은 예가 크롬입니다. Chrome은 모든 웹페이지 탭(스레드)의 관리자이지만 크롬은 멀티스레드이기 때문에 각 탭은 고유한 작은 프로그램입니다. 즉, 각 탭에 여러 코어를 배포할 경우 더 빠르게 실행할 수 있을 뿐만 아니라 한 탭이 ​​충돌할 때 전체 브라우저가 충돌하지 않는 것과 같은 다른 이점도 있습니다. 이것이 프로토스레딩이 멀티스레딩이 아닌 첫 번째 이유입니다. 우리는 MCU에서 작업할 코어가 하나뿐이므로 기존의 멀티스레딩은 완전히 불가능합니다. 우리는 단일 코어에서만 작업을 관리해야 하지만 동시에 여러 작업을 수행해야 합니다. 프로토스레딩이 필요합니다.

    그렇다면 프로토스레딩은 어떻게 다른가요?

    프로토스레딩은 제가 언급한 하이퍼스레딩과 어느 정도 유사합니다. 하이퍼스레딩은 두 번째 코어를 에뮬레이트하고 말 그대로 두 개의 가상 코어인 것처럼 가장하여 한 코어가 수행하는 작업을 나눕니다. 이것은 실제로 동일한 코어에 존재하고 동일한 리소스 공간을 공유했기 때문에 작동했습니다. arduino MCU는 하이퍼스레딩을 지원하지 않기 때문에 여기서는 할 수 없습니다. 프로토스레딩은 CPU 주기와 명령 대신 스케치에 의해 실행되는 코드의 '루프' 또는 '라인'으로 작업을 나눌 수 있다는 점을 제외하면 유사합니다. 상상할 수 있듯이 더 많은 작업을 수행하면 루프가 더 오래 걸리므로 각 프로젝트의 '초당 루프'가 크게 다릅니다. 프로토스레딩에는 다양한 구현이 있으며 여기에서 내가 사용하는 것은 아마도 조잡할 수 있지만 작동합니다. 기본적으로 각 루프에는 수행할 다른 작업이 없으며 기본 루프에서 덜 요구하거나 덜 자주 수행하는 작업을 수행합니다(또는 전혀 수행하지 않음). 바쁘지 않을 때는 아직 다른 작업 중 하나를 수행할 시간인지 확인하고 있습니다. 그렇다면 우리는 분기하여 수행합니다. "차단"하는 작업은 중단 없이 한 번에 모두 완료해야 하므로 일정 기간 동안 MCU를 묶어야 하는 작업(예:SD 카드에서 데이터 읽기 및 기타 몇 가지 작업) 계속 차단됩니다 다른 프로토스레드는 "정시에" 발생하지 않지만 변수 변경이나 출력 값 변경과 같은 빠른 작업을 한 번에 수행하는 두 개의 루프와 같은 간단한 작업의 경우 훌륭하게 작동합니다. 이것이 우리가 여기서 할 일입니다. 일부 MCU는 "차단" 작업으로 인해 발생하는 문제를 완화하는 데 도움이 될 수 있는 하이퍼스레딩과 유사한 멀티태스킹 기능을 제공할 수 있는 실시간 운영 체제(RTOS)를 지원합니다.

    시작하겠습니다.

    먼저 수행해야 할 작업을 파악합니다. 제 경우에는 (a) 깔끔한 "펄스" 효과를 위해 LCD 패널의 백라이트를 페이드 인 및 페이드 아웃하고 (b) 훨씬 더 느린(분할할 수 없는) 간격으로 숫자를 세고, (c) 훨씬 느린 간격으로 일부 문자열 메시지를 회전합니다. 이 프로세스가 원활하게 작동하는지 확인하기 위해 따라야 할 몇 가지 지침은 차단이 가장 적은 것부터 가장 많이 차단되는 것까지 기능을 평가하는 것입니다. 데이터 읽기 또는 기타 긴 지연과 같이 더 오래 걸리는 작업(이 시점부터 "함수"라고 함)과 실행 간격이 더 큰 함수가 가장 차단되는 기능입니다. 모든 루프는 아니지만 매우 자주 실행되고 완료하는 데 오래 걸리지 않는 함수는 최소 차단 함수입니다. 최소한의 차단 기능은 기본 "스레드"로 사용해야 하는 기능입니다. 어느 것이 위에 있는지 짐작할 수 있습니까?

    맞습니다. 백라이트를 켜고 끄는 "a"입니다. 이것은 규칙적이고 매우 빠른 간격으로 작업을 완료하는 것 외에는 화재 사이에 지연 없이 영구적이며 작업 자체는 매우 빠릅니다. 완벽한 관리자 스레드입니다.

    우리는 이 스레드(및 그 안의 모든 루프)를 사용하여 다른 스레드가 작업을 수행해야 하는지 확인합니다. 이 시점에서 코드를 읽는 것이 가장 좋습니다. 문서가 많이 있습니다. 하단을 향한 메인 루프를 참조하십시오. 내가 numberThread.check()를 호출하는 곳에서 스레드에 작업이 필요한지 확인하는 것을 볼 수 있습니다. 및 textThread.check() .

    메인 스레드의 루프 내에서도 이 작업을 수행해야 합니다. 그렇지 않으면 완료될 때까지 블록이 차단되기 때문입니다. 초기화 중에 스레드를 초기화하거나 코드의 설정 부분에서 스레드를 실행해야 하는 간격을 설정합니다. 이 스레드가 실행될 시간이면 .check() 메인 스레드를 계속하기 전에 이를 보고 작업을 수행합니다.

    간단히 말해서 그게 전부입니다. 나머지는 코드를 단계별로 살펴보면서 스스로 알아낼 수 있을 것입니다. 내가 그렇게 들릴지 모르지만 나는 어떤 방법으로든 프로토스레딩 전문가가 아닙니다. 이것은 내가 해킹한 간단한 예일 뿐입니다. 팁이 있거나 잘못된 부분이 있으면 피드백과 수정을 권장합니다! 감사합니다 :)

    <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

    코드

    <울>
  • 다중 스레드 LCD 코드 - multithread.ino(업데이트, v1.1)
  • 다중 스레드 LCD 코드 - multithread.ino(업데이트, v1.1)Arduino
    이 코드 비트는 라이브러리를 사용하여 하나의 Arduino Uno 프로세서에서 별도의 간격으로 3개의 반복 작업을 동시에 수행합니다. (a) 백라이트를 페이드 인 및 페이드 아웃하는 동안 (b) 숫자를 증가시키고 (c) 몇 개의 텍스트 문자열 사이를 회전합니다. 데모는 위의 비디오를 참조하십시오 :)
    /*Arduino Protothreading Example v1.1by Drew Alden(@ReanimationXP) 1/12/2016- 업데이트:v1.1 - 8/18/17 Arduino 1.6.6+ 프로토타이핑 변경됨 , 작은 수정. (사용 전에 함수 생성, foreach 및 관련 라이브러리 제거). TimedAction은 이제 구식입니다. TimedAction 및 WProgram.h / Arduino.h 오류에 대한 참고 사항을 읽으십시오.*///COMPONENTS/*이 코드는 Sunfounder Arduino 스타터 키트의 파란색 LCD를 사용하여 작성되었습니다. Amazon.com에서 다양한 키트로 찾을 수 있습니다. .*///THIRD-PARTY LIBRARIES//이것은 Arduino IDE 설치에 수동으로 추가해야 합니다.//TimedAction//이를 통해 별도의 시간 간격으로 수행할 작업을 설정할 수 있습니다.//http://playground.arduino.cc/Code /TimedAction//http://wiring.uniandes.edu.co/source/trunk/wiring/firmware/libraries/TimedAction#include //참고:이 라이브러리는 최신 버전의 Arduino에서 문제가 있습니다. 라이브러리를 다운로드한 후// 라이브러리 디렉토리로 이동하여// TimedAction.h를 편집해야 합니다. 내에서 Arduino.h//NATIVE LIBRARIES#include  /* LiquidCrystal Library - Hello World로 WProgram.h를 덮어씁니다. 16x2 LCD 디스플레이 사용을 보여줍니다. LiquidCrystal 라이브러리는 Hitachi HD44780 드라이버와 호환되는 모든 LCD 디스플레이에서 작동합니다. 많은 것들이 있으며 일반적으로 16핀 인터페이스로 구분할 수 있습니다. 회로 예:* LCD RS 핀 대 디지털 핀 12 * LCD Enable/E/EN 핀 대 디지털 핀 11 * LCD D4 핀 대 디지털 핀 5 * LCD D5 핀 대 디지털 핀 4 * LCD D6 핀 대 디지털 핀 3 * LCD D7 핀 대 디지털 핀 2 * LCD R/W 핀 대 접지 * LCD VSS 핀 대 접지 * LCD VCC/VDD 핀 대 5V * 10K 저항:* +5V 및 접지로 끝 * 와이퍼(중간)에서 LCD VO 핀( 핀 3) *백라이트 디스플레이:* 접지에 대한 LCD K 핀(있는 경우) * LCD A 핀에 대한 220ohm(빨간색 빨간색 검은색 검은색(갈색)) 저항, 핀 9에 대한 저항 이 예제 코드는 공개 도메인에 있습니다. http://www.arduino.cc/en/Tutorial/LiquidCrystal *///GLOBALSint 백라이트 핀 =9; // 백라이트 페이딩에 사용됨int timerCounter =0; // 카운터 증가. 결국 충돌합니다.int stringNo =0; //표시할 텍스트 문자열// "16 CHARACTER MAX"char* stringArray[]={"확인해 보세요... ", "쓰레드가 3개 있습니다", "한 번에...", "멋져요, 허 ?! :D "}; //INIT// 이것은 아마도 setup() 내부에서 수행되어야 하지만 무엇이든 간에.// 인터페이스 핀의 번호로 LCD 라이브러리를 초기화합니다.pinLiquidCrystal lcd(12, 11, 5, 4, 3, 2);//FUNCTIONS/ /이것이 우리의 첫 번째 작업입니다. LCD에 증가하는 숫자를 인쇄합니다. incrementNumber(){ // 커서를 열 0, 줄 1로 설정합니다. // (참고:줄 1은 두 번째 행입니다. 계산이 0으로 시작하기 때문에):lcd. setCursor(0, 1); // 카운터에 하나를 추가한 다음 표시합니다. 타이머 카운터 =타이머 카운터 + 1; lcd.print(timerCounter);}//두 번째 작업은 몇 초마다 실행되고 텍스트 문자열을 회전합니다.void changeText(){ // LCD에 메시지를 인쇄합니다. lcd.setCursor(0, 0); lcd.print(문자열배열[문자열번호]); // 배열 요소의 수를 가져오기 위한 험악한 해킹 if (stringNo>=sizeof(stringArray)/sizeof(char *)){ stringNo =0; 변경 텍스트(); } else{ stringNo =stringNo + 1; }}//x ms//edit마다 반복적으로 실행되는 몇 개의 타이머를 만듭니다. 이 줄은 incrementNumber 및 changeText// 함수 앞에 있었습니다. 이것은 함수가 아직 정의되지 않았기 때문에 작동하지 않았습니다!TimedAction numberThread =TimedAction(700,incrementNumber);TimedAction textThread =TimedAction(3000,changeText);// 세 번째 작업은 어디에 있습니까? 글쎄, 그것은 메인 루프 자체입니다 :) 가장 자주 반복되는 task//는 루프로 사용해야 합니다. other// 작업은 가장 빠르게 반복되는 작업을 "중단"할 수 있습니다. task.void setup() { //LCD의 열과 행 수를 정의합니다. lcd.begin(16, 2); //초기 문자열을 그리기 위해 changeText를 한 번 실행 [0] changeText();}void loop() { //스레드를 확인합니다. 시스템이 실행된 시간을 기준으로 ///실행해야 하고 작동해야 합니까? 그렇다면 해! numberThread.check(); textThread.check(); //세 번째 작업, 백라이트를 최소에서 최대 밝기로 페이드 인 //5포인트씩 증가:digitalWrite(13, HIGH); for (int fadeValue =0; fadeValue <=255; fadeValue +=10) { //잠시만요, 여기서 스레드를 확인하는 이유는 무엇입니까? // 이것은 for 루프이기 때문입니다. 메인 루프를 포함하여 발생하는 모든 // 루프 중에 스레드를 확인해야 합니다! numberThread.check(); textThread.check(); //값 설정(0에서 255 사이의 범위):analogWrite(backlightPin, fadeValue); // 디밍 효과를 보기 위해 20밀리초 동안 기다립니다. // 메인 루프에서 지연을 유지 SHORT. // 다른 스레드가 제 시간에 실행되는 것을 방지합니다. 지연(20); } //최대값에서 최소값으로 5포인트씩 페이드아웃합니다. digitalWrite(13, LOW); for (int fadeValue =255; fadeValue>=0; fadeValue -=10) { //쓰레드를 다시 확인 numberThread.check(); textThread.check(); //값 설정(0에서 255 사이의 범위):analogWrite(backlightPin, fadeValue); //디밍 효과를 보기 위해 20밀리초 동안 대기합니다. delay(20); } /* 앞으로 재미있는 스크롤 메시지를 위해... lcd.setCursor(15,0); // 커서를 열 15, 행 0으로 설정 for (int positionCounter1 =0; positionCounter1 <26; positionCounter1++) { lcd.scrollDisplayLeft(); //디스플레이의 내용을 왼쪽으로 한 칸 스크롤합니다. lcd.print(배열1[위치카운터1]); // LCD에 메시지를 인쇄합니다. 지연(팀); // 250마이크로초 동안 기다림 } lcd.clear(); //LCD 화면을 지우고 커서를 왼쪽 상단 모서리에 놓습니다. lcd.setCursor(15,1); // 커서를 열 15, 행 1 for (int positionCounter =0; positionCounter <26; positionCounter++){ lcd.scrollDisplayLeft(); //디스플레이의 내용을 왼쪽으로 한 칸 스크롤합니다. lcd.print(배열2[위치 카운터]); // LCD에 메시지를 인쇄합니다. 지연(팀); //250마이크로초 동안 기다림 } lcd.clear(); //LCD 화면을 지우고 커서를 왼쪽 상단 모서리에 놓습니다. */ }

    제조공정

    1. OpenSensor의 공기질 측정 방법
    2. Arduino RFID 잠금 자습서
    3. IR 리모콘 해킹 방법
    4. 키는 얼마입니까?
    5. 서미스터를 사용하는 것이 얼마나 쉬운가요?!
    6. Arduino로 음악을 만드는 방법
    7. Arduino와 함께 NMEA-0183을 사용하는 방법
    8. Arduino 지문 센서 자습서
    9. Arduino에서 Modbus를 사용하는 방법
    10. Arduino 튜토리얼 01:시작하기