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

ATmega 외계인 테마 슬롯 머신

구성품 및 소모품

Microchip Technology ATmega328
ATmega328P-PU, 정확히는 $3.00 SlotMachine용 하나, I2C 신용 LED 디스플레이용 하나 노예.
× 2
8자리의 7세그먼트 표시
$1.20 플레이어의 크레딧 잔액을 표시합니다.
× 1
8x8 매트릭스, 4개 세그먼트, MAX7219
$3.78 스피닝 릴을 시뮬레이션하고 기호를 표시합니다. 4개의 세그먼트 중 3개만 사용됩니다.
× 1
I2C 2004 직렬 파란색 백라이트 LCD 모듈 20 X 4 2004
$3.00 옵션 메뉴를 표시합니다. 알리익스프레스에서 쇼핑하세요. 배송비를 지불하지 마세요!
× 1
브레드보드(일반)
830 포인트$4.00
× 2
잠시 연락 버튼
50개에 $1.00. 하나는 릴 회전을 제어하고, 세 개는 메뉴 탐색, 두 개는 접지 핀 1 ATmegas의.
× 6
RGB 확산 공통 음극
다양한 신호를 보내는 데 사용됩니다.
× 1
LED(일반)
보드에 전원이 공급되고 있는지 여부를 나타냅니다.
× 1
저항 10k 옴
4는 각 버튼을 위로 당기고, 2는 ATmegas의 핀 1에 사용합니다.
× 6
저항 1k 옴
각 버튼과 ATmega 입력 핀 사이.
× 4
저항 330옴
RGB LED의 빨간색, 녹색 및 파란색 리드용
× 3
16MHz 크리스탈
하나는 SlotMachine의 ATmega328P-PU용이고 하나는 LED 디스플레이 슬레이브의 ATmega328P-PU용입니다. 둘 다 16MHz에서 실행됩니다.
× 2
슬라이드 스위치
전원 공급 장치용
× 1
부저
SlotMachine 칩용과 디스플레이 슬레이브 칩용으로 두 개가 필요합니다. 이 중 하나만 필요하고 두 마이크로 컨트롤러에서 공유할 수 있도록 회로를 수정하는 것이 좋습니다.
× 2
커패시터 22pF
× 4
0.10uF 커패시터
× 6
커패시터 100nF
선택 사항이며 SlotMachine 프로그래밍을 위해 Arduino Mini USB 직렬 어댑터를 사용하는 경우에만 필요합니다. 칩이 있습니다.
× 1
커패시터 10μF
공급 전압을 원활하게 하기 위해
× 2
선형 조정기(7805)
전압 공급을 조절하려면 5V입니다.
× 1
점퍼 와이어(일반)
많은 양이 필요합니다. 대부분 제가 직접 만들지만 점퍼 와이어도 사용합니다.
× 1
5v 전원 공급 장치
× 1
Arduino Mini USB 직렬 어댑터
$13.20 이것은 선택 사항이며 Arduino Uno를 사용하여 ATmega 328p-pu 칩을 프로그래밍할 수 있습니다.
× 1
FTDI USB-TTL 직렬 어댑터
$1.66 x 2 =$3.32 ATmega328P-PU 프로그래밍용. 회로도에는 표시되지 않습니다.
× 1
납땜 가능한 브레드보드
전체 크기의 납땜 가능한 브레드보드입니다.
× 1
SparkFun 납땜 가능 브레드보드 - 미니
× 1
포켓 땜납- 60/40 로진 코어 0.031" 직경
× 1
투명 플라스틱 방수 전자 프로젝트 상자 인클로저
$13.00 이것은 인클로저입니다.
× 1

필요한 도구 및 기계

납땜 인두(일반)
도움의 손길

앱 및 온라인 서비스

Arduino IDE
타이머 프리 톤 라이브러리
LED 제어 라이브러리
LiquidCrystal/LCD 라이브러리
LiquidCrystal I2C 라이브러리

이 프로젝트 정보

ATmega 외계인 테마 슬롯 머신

이 프로젝트는 두 개의 ATmega328P-PU 마이크로 컨트롤러를 사용하여 외계인 테마 슬롯 머신을 구현한 것입니다. 저는 Cory Potter의 Alien Invasion Slot Machine에서 영감을 얻었고 그 아이디어를 확장하고 싶었습니다. 슬롯 머신은 오락 및 교육 목적으로만 사용됩니다. 게임이 실제 슬롯 머신을 가능한 한 가깝게 시뮬레이션하도록 최선을 다했습니다. 프로젝트는 현재 브레드 보드입니다. 부품이 중국에서 도착하는 즉시 인클로저가 추가될 것이며 모든 것을 납땜할 기회가 있었습니다. 여가 시간에 프로젝트를 구축하는 데 약 2개월이 걸렸습니다. 저에게 빌드에서 가장 어려운 부분은 카지노 업계가 5억 정도의 시뮬레이션 후에 간단한 슬롯 머신이 작동할 것으로 예상하는 방식으로 게임을 작동시키는 것과 관련된 모든 수학을 이해하는 것이었습니다.

게임 작동 방식

이 게임에는 각 릴에 동일한 고유한 25개의 기호가 표시되는 3개의 릴이 있습니다(4개의 8x8 매트릭스가 있는 구성요소의 8x8 매트릭스 중 하나는 사용되지 않음). 이기는 방법에는 다섯 가지가 있습니다. 세 개의 우주선을 얻으면 잭팟을 얻습니다. 하나 또는 두 개의 우주선을 얻으면 일부 크레딧도 얻습니다. 일치하는 두 개 또는 세 개의 기호를 얻으면 승리합니다. 아래와 같이 우주선과 두 개의 기호가 일치하면 게임은 가장 낮은 확률/가장 높은 지불금으로 승리한 이벤트에 따라 지불합니다. 즉, 우승 이벤트는 상호 배타적이며, 한 번의 릴 회전으로 두 가지 다른 방법으로 우승할 수 없습니다. 이것은 프로그래밍을 조금 더 단순하게 유지했습니다. 저에게는 다른 많은 도전이 있었습니다.

기능

슬롯 머신에는 2개의 탐색 버튼과 선택 버튼을 사용하여 20 x 4 I2C 가능 LCD 디스플레이를 통해 액세스할 수 있는 몇 가지 흥미로운 기능이 있습니다. 버튼은 마이크로 컨트롤러의 외부 인터럽트 기능을 활용하는 상당히 정교한 디바운싱 알고리즘을 사용합니다. 메인 메뉴입니다.

메뉴에 6줄이 있으므로 전체 메뉴를 보려면 '아래로 이동' 버튼을 사용하여 아래로 스크롤해야 합니다. 릴 '회전' 전용 버튼이 있습니다. 그 외에도 메인 메뉴에서 '재생'을 선택할 수도 있습니다. 언제든지 베팅을 변경할 수 있습니다.

가장 흥미로운 기능은 게임을 '자동' 모드로 재생할 수 있다는 것입니다. 즉, LCD 화면의 설정 메뉴에서 자동 모드 옵션을 선택하면 해당 옵션을 다시 선택하거나 100만 회가 발생할 때까지 게임이 계속 반복됩니다. 게임 테스트를 위한 중요한 기능입니다. 여기에서 소리를 비활성화할 수도 있습니다.

LCD의 메뉴를 통해 시뮬레이션에서 생성된 모든 메트릭을 볼 수도 있습니다. USB 케이블을 사용하여 RX 및 TX 핀을 통해 마이크로 컨트롤러를 모니터에 연결하면 이러한 메트릭도 출력되고 직렬 모니터에서 볼 수 있습니다. 표시되는 측정항목 목록에는 신용 잔고, 대박을 친 횟수 및 다른 방법으로 크레딧을 획득한 횟수가 포함됩니다. 이를 통해 다양한 지불금을 기반으로 시뮬레이션을 실행할 수 있었고 지불금 테이블을 설정하고 증명하는 데 유용했습니다. 지불 테이블 자체는 구성할 수 없습니다. 일단 설정되면 동일하게 유지되어야 합니다. 지불 테이블을 구동하는 데 사용하여 변동성 지수를 구성할 수 있다고 생각하지만 훨씬 더 많은 작업이 필요합니다.

재설정 옵션을 사용하면 모든 메트릭(EEprom 쓰기 제외)을 다시 0으로 재설정할 수 있습니다. 이 칩은 EEprom에 대해 약 100,000번의 쓰기 작업을 수행합니다. 칩에서 사용할 수 있는 512k의 EEprom이 있고 그 중 일부만 사용하고 있기 때문에 쓰기 100,000개에 가까워지면 EEprom에서 메트릭 위치를 실제로 이동할 수 있습니다. 이 기능을 구현하지는 않았지만 칩의 수명을 연장하는 수단이 될 것입니다.

마지막으로 홀드 또는 하우스가 유지하는 각 베팅의 백분율(시간 경과에 따라)을 구성할 수 있습니다. 재설정 작업을 수행한 후 보류를 다시 설정해야 합니다.

플레이어의 신용 잔액은 항상 8자리 7세그먼트 디스플레이로 표시됩니다.

수학

게임이 현실감이 있는지 확인하기 위해 많은 노력을 기울였습니다. 게임이 허용 가능한 변동성 지수(VI)를 갖도록 확률을 계산하고 지불금 테이블을 설계했습니다. 이 지수는 기계의 동작이 얼마나 예측 가능한지를 측정합니다. VI가 높은 기계는 플레이어(또는 하우스)를 더 많은 돈으로 만들 가능성이 더 큽니다. VI가 낮은 기계보다 예측 가능성이 낮습니다. 동일한 게임이 다른 VI를 가진 다른 카지노(또는 동일한 카지노)에 존재한다는 것은 사실입니다. VI는 지불 일정을 조작하여 변경됩니다. 우리 게임의 경우 각 종류의 승리에 대한 확률과 지불금이 있습니다.

배당률(맨 오른쪽)과 지불금(맨 왼쪽)은 극적으로 다릅니다. 이 게임이 배당률 테이블이 일치하거나 확률을 밀접하게 따르도록 프로그래밍된 경우 VI는 허용할 수 없을 정도로 높을 것입니다. 보류는 지불금의 백분율로 계산되며 하우스/카지노에서 보관하는 베팅의 일부입니다. 명시된 대로 LCD 메뉴를 통해 보류를 설정할 수 있습니다. 관할 구역마다 슬롯 머신에 대한 최대 보류를 관리하는 규정이 다릅니다. 일반적인 최대 보류는 15%입니다. 홀드를 법이 허용하는 최대값으로 설정한다고 해서 반드시 해당 머신에서 발생하는 이익이 최대화되는 것은 아니라는 점을 이해하십시오. 홀드가 높을수록 플레이어가 머신을 사용하는 것을 방해할 수 있기 때문입니다. 그러나 나는 많은 플레이어가 일반적으로 작은 글씨에 묻혀 있는 홀드를 무시하고 기계에 대한 수요 곡선이 상대적으로 수직적이라고 생각합니다(즉, 홀드인 기계 사용 비용은 대부분 무시됨). 기계에 의해 생성되는 이익은 게임 자체의 디자인뿐만 아니라 기계의 위치나 배치에 훨씬 더 많이 의존합니다. 그러나 그것은 추측일 뿐입니다. 나는 홀드에 민감한 정통한 도박꾼이 있다고 확신합니다.

코드와 함께 사용할 수 있는 스프레드시트와 세 개의 테이블은 게임이 올바르게 작동하고 있음을 증명하기 위해 작성되었습니다(첫 번째 테이블은 위에 나타남). 스프레드시트 작성의 첫 번째 단계는 각 승리 유형의 확률을 정확하게 계산하는 것이었습니다(계산된 확률 열).

3개의 우주선

3개의 우주선이 나타날 확률은 가능한 조합의 총 수의 역수입니다. 가능한 조합의 총 수에 대해 우승 조합의 수는 15625입니다. 각 릴에는 25개의 고유한 기호가 있으므로 확률은 1/(25 x 25 x 25) 또는 0.000064입니다. 그러면 확률 1/확률 - 1이 1에서 15624까지가 됩니다. 여기에서 확률에서 확률을 계산하는 방법을 배웠습니다.

Three Symbols Match(우주선 제외)

우주선이 아닌 3개의 기호가 일치할 확률은 24(각 릴의 고유 기호 수에서 우주선을 뺀 수)를 가능한 조합 수로 나눈 값입니다. 24는 3개의 기호가 일치하는 조합이 24개 있기 때문에 분자입니다. 24/15625 =0.001536. 그 확률은 약 1에서 650.04입니다.

2개의 우주선

일치하는 두 우주선의 총 24 x 3 조합이 있습니다. 우주선을 2개 맞추는 방법이 있기 때문입니다. X =우주선, Y =다른 기호 XXY, XYX 및 YXX를 지정합니다. Y에는 24개의 가능한 값이 있습니다. 따라서 24 X 3 / 15625 =0.004608입니다. 확률은 1에서 216.01 사이입니다.

우주선 하나 등장

각 릴에 대해 단일 우주선이 나타날 수 있는 24 x 24 조합이 있습니다.

우주선은 모든 릴에 나타날 수 있으므로 단일 릴에서 사용할 수 있는 조합 수에 3개의 릴을 곱해야 합니다. 따라서 확률은 24 x 24 x 3 / 15625 =0.110592입니다. 확률은 1에서 8.04입니다.

두 기호 일치

우주선을 제외하고 주어진 2개의 기호에 대해 우주선이 아닌 23개(25에서 하나의 우주선에서 3개의 기호 일치를 만드는 하나의 기호를 뺀 것) x 3개의 릴 x 24개의 기호가 있습니다. 확률은 (23 X 3 X 24)/15625 =0.105984입니다. 확률은 1에서 8.44입니다.

이제 각 종류의 승리에 대한 확률이 있으므로 스프레드시트를 사용하여 변동성 지수를 수용할 수 있는 방식(<~20)으로 만드는 방식으로 지불금 테이블을 설계할 수 있습니다. 이 작업을 수행하는 방법을 이해하기 위해 이 게시물에 크게 의존했습니다. VI가 20 미만이고 셀 J10의 합계가 내가 얻을 수 있는 한 0에 가까울 때까지 시행착오의 과정을 사용하여 첫 번째 테이블의 House income 열에 값을 입력했습니다. 이 값을 사용하여 SlotMachine.ino에서 THREE_SPACESHIP_PAYOUT, THREE_SYMBOL_PAYOUT, TWO_SPACESHIP_PAYOUT, ONE_SPACESHIP_PAYOUT 및 TWO_SYMBOL_PAYOUT을 적절하게 설정했습니다. 그런 다음 먼저 0% 유지를 사용하여 1,000,001번의 재생에 대해 5번의 시뮬레이션을 실행하고 메트릭 메뉴의 값을 실제 결과 테이블(세 번째 테이블)의 적절한 행과 열에 입력했습니다.

실제 확률이 계산된 확률과 밀접하게 추적되고 Pct Diff Prob 열이 합리적임을 관찰했습니다. 또한 House Pay 행의 값을 잠재적 소득 이해 테이블(두 번째 테이블)의 1, 000, 000 행에 있는 고소득 및 저소득 열의 값 범위와 일치시켰습니다. 실제 결과 테이블은 고소득 및 저소득 열에 지정된 범위 내에 있었습니다. 잠재적 소득 이해 테이블은 90% 신뢰 구간을 사용하여 주어진 보류 값에 대한 예상 소득 범위를 정의합니다. 아래 예에서는 보류가 0으로 설정되어 있으므로 승리 가능성이 패배 가능성과 일치합니다. 게임을 100만 번 플레이하면 수입이 16,432에서 -16,432 사이일 가능성이 90%입니다.

스프레드시트와 프로그램으로 작업하고 수백만 번의 시뮬레이션을 실행한 후 프로그램의 결함을 해결하고 스프레드시트의 결함을 해결하며 VI <20을 유지하는 지불금 테이블의 값을 정의할 수 있었습니다. 마지막으로 저는 다음을 변경했습니다. 15%로 유지하고 5개의 시뮬레이션을 실행하여 실제 상황에서 게임 수입이 예상과 일치하는지 확인했습니다. 다음은 15% 보류에 대한 수입 테이블입니다.

다음은 실제 결과입니다.

지불금 값을 설정하는 이면의 모든 수학을 정말로 이해하고 싶다면 스프레드시트의 공식을 검토하는 것이 좋습니다. 오류를 발견하면 친절하게 저에게 지적해 주십시오. 저는 수학자(또는 C 프로그래머)가 아니므로 표준 면책 조항이 적용됩니다.

코드

코드를 한 줄씩 설명하지 않겠습니다. 그것은 광범위하게 주석을 달았고 어디에서나 까다로운 일이 없습니다. 따라서 Force를 사용하고 소스를 읽으십시오. ATmega386의 레지스터 조작에 익숙하지 않고 Arduino 라이브러리에 의존하지 않고 AVR 마이크로 컨트롤러용 코드를 작성하는 방법에 대해 더 알고 싶다면 Elliott William's 훌륭한 책, "Make:AVR 프로그래밍". safaribooksonline.com에 대한 구독이 있는 경우 거기에서 찾을 수 있습니다. 그렇지 않으면 여기 Amazon에서 사용할 수 있습니다. 이 프로그램에서 나는 어떤 곳에서는 Arduino 기능을 사용하고 다른 곳에서는 레지스터를 직접 조작합니다. 죄송합니다.

가장 먼저 알 수 있는 것은 프로그램이 전역 변수를 광범위하게 사용한다는 것입니다. Stack Overflow에 이 주제에 대한 좋은 토론이 있습니다. 나는 여기서 전역 변수의 과도한 사용을 옹호하거나 옹호하지 않을 것이지만, 이 주제에 대한 모든 관점을 이해하고 단일 프로그래머와 제한된 리소스가 있는 임베디드 응용 프로그램 프로젝트에서 전역 변수를 사용하는 것에 대한 강력한 주장이 있음을 인식하는 것이 좋습니다. .

나는이 프로젝트가 나에게 불가능했을 일부 라이브러리를 사용합니다. Timer Free Tone Library는 패시브 피에조 스피커를 통해 다양한 주파수를 구동하는 데 사용됩니다. SlotMachine.h에는 음표에 대한 정의가 많다는 것을 알 수 있습니다. 이를 사용하여 원하는 멜로디를 조합할 수 있습니다. 나는 SlotMachine의 마이크로 컨트롤러가 시작되고 설정 기능이 실행될 때 "제3의 종류의 가까운 만남" 테마의 일부를 재생하기 위해 그 중 소수만 사용합니다. 타이머가 필요할 것 같아서 타이머 프리 라이브러리를 선택했는데 결국 타이머를 전혀 사용하지 않게 되었습니다. 필요한 경우 사용할 수 있습니다. LED 제어 라이브러리는 SlotMachine.ino와 slotCreditDisplaySlave.ino에서 모두 사용됩니다. 전자에서는 슬롯 머신 릴 역할을 하는 3개의 8 x 8 LED 매트릭스를 제어하는 ​​데 사용됩니다. slotCreditDisplaySlave.ino에서 라이브러리는 플레이어의 신용 잔액을 표시하는 8자리 7세그먼트 디스플레이에 대한 액세스를 용이하게 합니다. 지금은 신용 잔액을 제공하기 위해 다른 AVR 칩(ATmega328)을 사용하지 않으려고 노력했지만 8 x 8 행렬과 8자리 7세그먼트 디스플레이를 단일 마이크로 컨트롤러. 그래서 결국 그 목적을 위해 I2C 슬레이브를 만들어야 했습니다. 더 저렴한 AVR을 사용하여 크레딧 잔액을 표시할 수 있는 경우가 분명하지만 이 기사에서는 간단하게 하기 위해 다른 ATmega328P-PU 칩을 사용하기로 결정했습니다. 밝은 측면에서, 큰 잭팟에 당첨되면 크레딧은 계속해서 계속해서 회전할 수 있는 동안 크레딧 디스플레이 슬레이브에 계속 계산됩니다. 20줄 x 4줄 LCD 디스플레이에 쉽게 액세스하려면 LiquidCrystal/LCD 및 LiquidCrystal I2C 라이브러리가 필요합니다. 언급했듯이 LCD_SCREEN_HEIGHT의 정의를 4에서 2로 변경하기만 하면 손에 있는 것이 전부인 경우 20 x 2 LCD로 대체할 수 있습니다. 이 프로젝트에 대해 획득한 LCD 디스플레이가 I2C를 지원하는지 확인하십시오. 그렇지 않은 경우 LCD1602 어댑터 플레이트용 I2C SPI 직렬 인터페이스 보드 포트 모듈, 부품 번호 PCF8574(아래 그림 참조)를 구입하여 LCD1602 디스플레이에 납땜해야 합니다.

게임은 동시에 여러 다른 상태에 있을 수 있으며 machineState 변수는 상태를 추적합니다. 예를 들어, '회전'하고 동시에 '자동 모드'일 수 있습니다. 저는 프로그램 내부에서 이 개념을 많이 사용하지 않습니다. 어쨌든 다른 프로그램에서만큼은 아닙니다. 그러나 상태에 따라 일부 조건부 분기가 있습니다. 이벤트의 개념도 있으며 이벤트는 ProcessEvents 함수에서 전달 및 처리됩니다. 이벤트 대기열이 있었으면 더 좋았을 텐데 그렇게까지 하지는 않았어요.

SlotMachine.ino의 주석 섹션에는 알려진 결함 목록과 '해야 할 일'이 있습니다. 때때로 릴을 '회전'할 때(회전 버튼을 누르거나 LCD 메뉴에서 '재생' 옵션을 선택하여) 하나 또는 두 개의 릴이 움직이지 않습니다. 그 이유는 장면 뒤에서 난수 생성기가 해당 릴에 대해 이미 표시되는 기호를 선택했기 때문입니다. 이것은 게임을 보다 사실적으로 보이게 하기 위해 수정될 수 있지만 실제로는 결함이 아닙니다. 릴은 대부분의 슬롯 머신에서와 같이 왼쪽에서 오른쪽으로 회전을 끝내지 않습니다. 이것은 일을 단순하게 유지하기 위해 의도적으로 수행됩니다. 릴이 실제로 회전하기 전에 각 스핀에 대해 생성된 세 개의 난수를 오름차순으로 정렬하여 릴이 왼쪽에서 오른쪽으로 회전을 마치도록 할 수 있었고 나는 신경 쓰지 않았습니다.

'해야 할 일'에 관해서는, 나는 단지 운동을 통해 그것을 하는 방법을 배우기 위해 브라운 아웃 보호를 추가하고 강아지 보호를 관찰하고 싶습니다. 전역 변수에 할당된 공간의 80%가 이미 사용되었습니다. 이것은 ATmega386 및 Arduino 프로그램에서 상황이 불안정해지기 시작할 수 있는 지점입니다. 우리는 이 프로그램과 함께 그 시점에 있습니다. 계속 작동하도록 예산을 편성해야 했으며 프로그램에 전역 항목을 더 이상 추가하지 않는 것이 좋습니다. 예를 들어 메뉴가 전역 변수 공간을 많이 차지하기 때문에 메뉴의 설정 부분에 더 많은 기능을 추가하기가 어렵습니다. 메뉴를 프로그램 메모리로 이동하여 전역 변수 문제를 해결하려고했지만 전역에서 사용하는 공간을 줄이기 위해 그것을 얻을 수 없었습니다. 컴파일러가 어쨌든 메뉴에 대한 모든 공간을 미리 할당해야하기 때문에 생각합니다 . 게임에 약간의 재미를 더하기 위해 더 많은 작업을 수행할 수 있습니다. RGB LED와 피에조 부저를 더 잘 활용하고, 우승을 조금 더 축하하고, 돈을 잃었을 때 더 나은 소리를 낼 수 있지만, 그걸 가지고 놀고 싶은 사람에게 맡기겠습니다.

게임의 모든 심볼을 디자인해야 했습니다. 그들 중 일부는 고전 아케이드 게임 'Space Invaders'를 생각나게 하고, 나는 그것들을 어딘가에서 빌렸을 것입니다. 나머지는 제가 손으로 디자인했으며 일부는 전문가 수준이 아닙니다. 이 사이트를 사용하여 기호를 디자인하는 데 도움을 받았습니다. 기호를 조정하려면 SlotMachine.h에서 조정하고 마음껏 사용하세요. 프로그램 논리에는 영향을 미치지 않습니다. 기호의 경우 텍스트 편집기로 디자인할 수 있도록 기본 2/2진수로 숫자를 나타냅니다.

코드는 여기 GitHub에서 사용할 수 있습니다.

슬롯 머신 구축

저는 두 ATmega328P-PU 마이크로 컨트롤러를 제자리에서 프로그래밍하기 위해 직렬 보드에 FTDI USB를 사용했습니다. 이러한 연결은 Fritzing 회로도에 표시되지 않습니다. 무납땜 브레드보드에 FTDI 브레이크아웃 보드를 설정하는 방법에 대한 지침은 이 링크를 따르십시오. 설정을 제대로 하려면 구글링을 조금 해야 할 수도 있습니다. 이 게시물이 FTDI 브레이크아웃 보드를 통해 프로그래밍을 시작할 때 마이크로 컨트롤러가 자동으로 재설정되도록 하려고 했던 문제를 해결하는 데 도움이 되었다고 생각합니다. ATmega328 리셋 핀(위치 1/PC6/리셋 핀)과 FTDI 브레이크아웃 보드의 RTS 사이의 연결과 직렬로 100nF 커패시터를 배치하여 원할 때 리셋 버튼을 누르고 있을 필요가 없도록 하십시오. 칩을 프로그래밍합니다. Arduino Uno를 사용하여 칩을 프로그래밍하기로 선택한 경우 여기에서 지침을 찾을 수 있습니다. If you're just going to program the chips once with the supplied code it's probably quickest and easiest to just program them from the Arduino Uno.

Both mico-controllers are set up with the 'Arduino' chip (the ATmega328P-PU) on the breadboard. If you're planning on ultimately building this project by soldering the components together, or if you just want to copy what I've done here when you breadboard the project, you'll want to understand how to set up the Arduino on a breadboard. Follow the excellent instructions here for doing that. Those instructions include the procedure necessary to follow if you need to load the Arduino bootloader on the two chips, which you will most likely need to do if you purchase the chips from a supplier in China and/or via e-bay, as suggested here in the part's list. To do that you'll need an AVR programmer like the AVRISP mk II or the USBTiny ISP. You can also just use your Arduino, if you have one, to burn the bootloader. All of your options are explained when you follow the link above.

Parts

If you have some of the smaller components in your inventory already (resistors, capacitors, the crystal and the regulator) then you can get away with spending <$40 on parts for this build. If you add in the cost of the enclosure and the perfboard, it's probably approaching $60. I've tried to include the supplier I used for all of the pieces. I use AliExpress.com, Amazon.com, and ebay.com for most of my parts and tools, and all of these parts are easily sourced at any of those locations. Also, if you don't want to purchase a 20 x 4 LCD display, and you already have a 20 x 2 LCD display on hand, you can simply change LCD_SCREEN_HEIGHT in SlotMachine.ino from 4 to 2.

Here is the enclosure I've ordered, into which I'll insert the components:

This item is available here for $13.80. That's a little on the pricey side in my view. I'm hoping that everything will fit and that the top is very transparent so that I don't have to cut holes in it to see the reels and the credit balance display. We'll see how it goes when it gets here! Suggestions welcome.

Software

All of these libraries listed in the parts section will need to be installed into your Arduino development environment if you wish to compile the code so that you can upload it onto your ATmega chip. This page explains how to install an Arduino library.

Hand Tools

<울>
  • Soldering iron
  • Helping Hands
  • Schematic

    The Fritzing schematic is available here, and the.fzz file is included with the code on GitHub.

    Below I've included some directions on wiring the micro-controllers, because the Fritzing diagram is crowded. This doesn't represent all of the connections necessary, but it should clear up any confusion. I haven't grounded all of the unused pins, but I am probably going to do that in the final product. If you're having trouble following the Fritzing diagram with respect to setting up the circuitry for the power supply, remember to look here, under Adding circuitry for a power supply . Remember to add the switch between the breadboard ground rail and the power supply circuit so that you can power the circuit off and on without having to unplug or disconnect the power supply. That will be important when we put everything into an enclosure.

    Slot Machine

    <울>
  • Pin 1 - RTS on the FTDI USB to Serial break out board, reset button
  • Pin 2 - TXD on the FTDI USB to Serial break out board
  • Pin 3 - RXD on the FTDI USB to Serial break out board
  • Pin 4 - 1K ohm resistor - momentary 'spin' button
  • Pin 5 - 330 ohm resistor - RGB LED blue pin
  • Pin 6 - unused, consider grounding it
  • Pin 7 VCC - breadboard power rail, 0.1uF capacitor
  • Pin 8 GND - breadboard ground rail, 0.1uF capacitor
  • Pin 9 XTAL1 - 16MHz crystal, 22pF capacitor to breadboard ground rail
  • Pin 10 XTAL2 - 16MHz crystal, 22pF capacitor to breadboard ground rail
  • Pin 11 - unused, consider grounding it
  • Pin 12 - unused, consider grounding it
  • Pin 13 - unused, consider grounding it
  • Pin 14 - DIN on the 8x8 matrices
  • Pin 15 - 330 ohm resistor - RGB LED red pin
  • Pin 16 - 330 ohm resistor - RGB LED green pin
  • Pin 17 - piezo buzzer positive - negative piezo buzzer - breadboard ground rail
  • Pin 18 - CS on the 8x8 matrices
  • Pin 19 - CLK on the 8x8 matrices
  • Pin 20 AVCC - breadboard power rail, 0.1uF capacitor
  • Pin 21 AREF - breadboard power rail
  • Pin 22 GND - breadboard ground rail
  • Pin 23 - leave this pin floating, it's used to seed the random number generator
  • Pin 24 - 1K ohm resistor - momentary 'navigate up' button
  • Pin 25 - 1K ohm resistor - momentary 'navigate down' button
  • Pin 26 - 1K ohm resistor - momentary 'select' button
  • Pin 27 SDA - Pin 27 SDA on the display I2C ATmega328P-PU slave
  • Pin 28 SCL - Pin 28 SCL on the display I2C ATmega328P-PU slave
  • Display Slave

    <울>
  • Pin 1 - RTS on the FTDI USB to Serial break out board, reset button
  • Pin 2 - TXD on the FTDI USB to Serial break out board
  • Pin 3 - RXD on the FTDI USB to Serial break out board
  • Pin 4 - unused, consider grounding it
  • Pin 5 - unused, consider grounding it
  • Pin 6 - unused, consider grounding it
  • Pin 7 VCC - breadboard power rail, 0.1uF capacitor
  • Pin 8 GND - breadboard ground rail, 0.1uF capacitor
  • Pin 9 XTAL1 - 16MHz crystal, 22pF capacitor to breadboard ground rail
  • Pin 10 XTAL2 - 16MHz crystal, 22pF capacitor to breadboard ground rail
  • Pin 11 - unused, consider grounding it
  • Pin 12 - unused, consider grounding it
  • Pin 13 - unused, consider grounding it
  • Pin 14 - unused, consider grounding it
  • Pin 15 - piezo buzzer positive - negative piezo buzzer - breadboard ground rail
  • Pin 16 - CS on the seven segment display
  • Pin 17 - CLK on the seven segment display
  • Pin 18 - DIN on the seven segment display
  • Pin 19 - unused, consider grounding it
  • Pin 20 AVCC - breadboard power rail, 0.1uF capacitor
  • Pin 21 AREF - breadboard power rail
  • Pin 22 GND - breadboard ground rail
  • Pin 23 - unused, consider grounding it
  • Pin 24 - unused, consider grounding it
  • Pin 25 - unused, consider grounding it
  • Pin 26 - unused, consider grounding it
  • Pin 27 SDA - Pin 27 SDA on the slot machine I2C ATmega328P-PU
  • Pin 28 SCL - Pin 28 SCL on the slot machineI2C ATmega328P-PU
  • 요약

    This project was a lot of fun to build. The most challenging part was understanding all of the math necessary to create a payout table that works. I hope you can have fun with this project too, if you decide to build it. If you have any problems, questions, or, most importantly, discover any defects in the code or with the math, please contact me so I can fix any problems! My email address is [email protected]. I'll be creating part II of this article when I enclose all of the components.

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

    코드

    <울>
  • SlotMachine.ino
  • SlotMachine.h
  • slotCreditsDisplaySlave.ino
  • SlotMachine.inoArduino
    /*SlotMachine.ino Version:1.0 Date:2018/07/01 - 2018/08/29 Device:ATMega328P-PU @ 16mHz Language:C Purpose =======A slot machine for entertainment and educational purposes only, with the following features:- AtMega328P microcontroller running at 16mHz - Custom I2C seven segment display for displaying credit balance, also built with an ATMega328P running at 16mHz. That program is supplied in a seperate file. - Three 8x8 LED matricies for displaying symbols driven by MAX7219. - I2C LCD display 20x4, to show menus - various buzzers, buttons and an RGB LED. - the ability to update various settings via the LCD menu to influence the machine's behavior. - the ability to change the amount of the wager. Known Defects =============- Sometimes one or two of the reels won't spin, not really a defect. - crash as soon as payed out exceeds 1,000,000. TODO ====- add brown out detection - add watch dog protection (wdt_enable(value), wdt_reset(), WDTO_1S, WDTO_250MS) Warnings ========- Beware of turning on too much debugging, it's easy to use all of the data memory, and in general this makes the microcontroller unstable. - Gambling is a tax on people who are bad at math. This is for entertainment only. It was the intent of the author to program this game to return ~%hold of every wager to the house, similar to many slot machines. - Why not control the LED that displays the credits with the LedControl library? I tried that and couldn't get more than one LedControl object to work at a time. So I had to create an I2C slave instead and use another AVR. Suggestions ===========- Best viewed in an editor w/ 160 columns, most comments are at column 80 - Please submit defects you find so I can improve the quality of the program and learn more about embedded programming. Author ======- Copyright 2018, Daniel Murphy  - Contributors:Source code has been pulled from all over the internet, it would be impossible for me to cite all contributors. Special thanks to Elliott Williams for his essential book "Make:AVR Programming", which is highly recommended. Thanks also to Cory Potter, who gave me the idea to do this. License =======Daniel J. Murphy hereby disclaims all copyright interest in this program written by Daniel J. Murphy. 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 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 . Libraries =========- https://github.com/wayoda/LedControl - https://bitbucket.org/teckel12/arduino-timer-free-tone/wiki/Home - https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library - https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home The Program ===========- Includes */#include #include #include  // for the abs function#include "LedControl.h" // https://github.com/wayoda/LedControl#include "SlotMachine.h"#include  // https://bitbucket.org/teckel12/arduino-timer-free-tone/wiki/Home#include #include  // https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home#include  // https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library//- Payout Table/* Probabilities based on a 1 credit wager Three spaceships:1 / (25 * 25 * 25) =0.000064 Any three symbols:24 / 15625 =0.001536 Two spaceships:(24 * 3) / 15625 =0.004608 One spaceship:(24 * 24 * 3)/ 15625 =0.110592 Two symbols match:(23 * 3 * 24) / 15625 =0.105984 House win, 1 minus sum of all probabilities =0.777216 _ Use the spreadsheet to work out the payout table remembering to keep the volatility resonable i.e. <20. P R O O F Actual Actual Winning Combination Payout Probablility Count Probability ========================================================*/#define THREE_SPACESHIP_PAYOUT 600 // 0.000064 0.00006860 see the excel spreadsheet #define THREE_SYMBOL_PAYOUT 122 // 0.001536 0.00151760 that accompanies this program.#define TWO_SPACESHIP_PAYOUT 50 // 0.004608 0.00468740#define ONE_SPACESHIP_PAYOUT 3 // 0.110592 0.11064389#define TWO_SYMBOL_PAYOUT 2 // 0.105984 0.10575249//// With these payouts the Volatility Index is 16.43////- Macros#define ClearBit(x,y) x &=~y#define SetBit(x,y) x |=y#define ClearBitNo(x,y) x &=~_BV(y) #define SetState(x) SetBit(machineState, x)//- Defines#define DEBUG 1 // turns on (1) and off (0) output from debug* functions#define BAUD_RATE 38400 // Baud rate for the Serial monitor #define NUMFRAMES 25 // Number of symbols in each "reel" or "slot". e.g three reels:|7|7|7|#define LINESPERFRAME 8 // each line corresponds to one row on the 8x8 dot matrix LED#define FRAME_DELAY 100 // milliseconds, controls the speed of the spinning reels#define NUMREELS 3 // the hardware (8x8 matricies) accomodates 4 reels, we're only using three now #define DEBOUNCE_TIME 1000 // microseconds (changed from 500 to 1000 to cut down on double press problem) #define BUTTON_DDR DDRD // this accomodates the button that starts the reels spinning#define BUTTON_PORT PORTD#define BUTTON_PIN PIND#define PCMSK_BUTTON PCMSK2#define PCIE_BUTTON PCIE2 #define BUTTON_SPIN_PIN DDD2 // the actual spin button#define BUTTON_SPIN_INT PCINT18#define BUTTON_SPIN_PORT PORTD2 #define NAV_DDR DDRC // this is for the buttons that control menu navigation on the 20x4 LCD#define NAV_PORT PORTC#define NAV_PIN PINC#define PCMSK_NAV PCMSK1#define PCIE_NAV PCIE1 #define NAV_UP_PIN DDC1 // Navigate up button#define NAV_UP_INT PCINT9#define NAV_UP_PORT PORTC1 #define NAV_DOWN_PIN DDC2 // Navigate down button#define NAV_DOWN_INT PCINT10#define NAV_DOWN_PORT PORTC2 #define SELECT_PIN DDC3 // Select current menu item button#define SELECT_INT PCINT11#define SELECT_PORT PORTC3 #define BUZZER_DDR DDRB // This is for the slot machines piezo buzzer#define BUZZER_PORT PORTB#define BUZZER_PIN DDB3#define TONE_PIN 11 // Pin you have speaker/piezo connected to (TODO:be sure to include a 100ohm resistor).#define EVENT_NONE 0 // These are all of the various events that can occur in the machine#define EVENT_SPIN 1#define EVENT_SHOW_MENU 2 #define EVENT_SELECT 3#define EVENT_NAV_UP 4#define EVENT_NAV_DOWN 5#define EVENT_BACK 6#define EVENT_PLAY 10#define EVENT_BET 11#define EVENT_SETTINGS 12#define EVENT_VIEW_METRICS 13#define EVENT_RESET 14#define EVENT_HOLD 15#define STATE_IDLE B00000001 // These are the various states the machine can be in, not all are#define STATE_SPINNING B00000010 // mutually exclusive.#define STATE_AUTO B00000100 // This state is for automatically running the program to gather metrics.#define STATE_SHOW_MENU B00001000 // State we're in when showing the menu. Note you can spin and show menu // concurrently.#define MINIMUM_WAGER 5 // TODO:consider this something that can be changed via settings#define WAGER_INCREMENT 5 // TODO:consider this something that can be changed via settings#define ONE_SECOND 1000 // # milliseconds in one second. Used to control how long the siren sounds. #define SHIP_LOC 144 // Location of various symbols in the array of symbols maintained in SlotMachine.h#define ALIEN_1_LOC 152 // needed for animation#define ALIEN_2_LOC 160#define EEPROM_FREQ 10000 // Write to EEPROM every Nth play#define AUTO_MODE_MAX 1000000 // stop after this many plays in auto mode#define RED 1 // TODO:should we use an enum here? Must be a better way...#define GREEN 2#define BLUE 3#define PURPLE 4#define WHITE 5#define OFF 6#define MAX_NOTE 4978 // Maximum high tone in hertz. Used for siren.#define MIN_NOTE 31 // Minimum low tone in hertz. Used for siren.#define STARTING_CREDIT_BALANCE 500 // Number of credits you have at "factory reset".#define DEFAULT_HOLD 0 // default hold is zero, over time the machine pays out whatever is wagered#define NUM_LED_DATAIN 7#define NUM_LED_CLK 6#define NUM_LED_LOAD 5#define NUM_CHIP_COUNT 1#define MATRIX_LED_DATAIN 8#define MATRIX_LED_CLK 13#define MATRIX_LED_LOAD 12#define MATRIX_CHIP_COUNT 4#define LOW_INTENSITY 1 // dim#define HIGH_INTENSITY 10 // bright#define SIREN_FLASHES 1#define LCD_SCREEN_WIDTH 20#define LCD_SCREEN_HEIGHT 4#define CREDITS_I2C_SLAVE_ADDR 0x10 // I2C addresses#define LCD_I2C_ADDR 0x3F // LCD display w/ 4 lines#define BACKLIGHT_PIN 3#define En_pin 2#define Rw_pin 1#define Rs_pin 0#define D4_pin 4#define D5_pin 5#define D6_pin 6#define D7_pin 7#define MENU_SIZE 17#define MAIN_MENU_NUMBER 0#define MAIN_MENU_ELEMENTS 6char *mainMenu[] ={ "Play", "Bet", "Settings", "Metrics", "Reset", "Hold", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " };#define BET_MENU_NUMBER 1#define BET_MENU_ELEMENTS 3char *betMenu[] ={ "+5 credits:", // TODO:make this dynamic based on WAGER_INCREMENT "-5 credits:", "Back", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " };#define SETTINGS_MENU_NUMBER 2#define SETTINGS_MENU_ELEMENTS 3#define SETTINGS_BACK_ITEM 2char *settingsMenu[] ={ "Auto/Manual", // TODO:fill out this menu with more cool options "Toggle Sound ", "Back ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " };#define METRICS_MENU_NUMBER 3#define METRICS_MENU_ELEMENTS 15char *metricsMenu[METRICS_MENU_ELEMENTS];#define HOLD_MENU_NUMBER 4#define HOLD_MENU_ELEMENTS 3char *holdMenu[] ={ "+1 percent:", "-1 percent:", "Back", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " " };int selectPos =0;int menuNumber =MAIN_MENU_NUMBER;int elements =MAIN_MENU_ELEMENTS;char *currentMenu[MENU_SIZE];LiquidCrystal_I2C lcd( LCD_I2C_ADDR, // Create the LCD display object for the 20x4 display En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin );LedControl lc=LedControl( MATRIX_LED_DATAIN, // Create the LED display object for the 8x8 matrix MATRIX_LED_CLK, MATRIX_LED_LOAD, MATRIX_CHIP_COUNT ); // Pins:DIN,CLK,CS, # of chips connectedvolatile int reelArrayPos[NUMREELS];volatile byte machineState;volatile byte event =EVENT_NONE;volatile byte color =RED;#define ADC_READ_PIN 0 // we read the voltage from this floating pin to seed the random number generator#define RED_PIN 9 // Pin locations for the RGB LED#define GREEN_PIN 10#define BLUE_PIN 3#define NUM_NOTES 5 // The number of notes in the melody // EEProm address locations#define PAYEDOUT_ADDR 0x00 // 4 bytes#define WAGERED_ADDR 0x04 // 4 bytes#define PLAYED_ADDR 0x08 // 4 bytes#define TWO_MATCH_ADDR 0x12 // 4 bytes#define THREE_MATCH_ADDR 0x16 // 2 bytes#define SHIP_ONE_MATCH_ADDR 0x18 // 4 bytes#define SHIP_TWO_MATCH_ADDR 0x22 // 2 bytes#define SHIP_THREE_MATCH_ADDR 0x24 // 2 bytes#define EEPROM_WRITES_ADDR 0x34 // 4 bytes#define RESET_FLAG_ADDR 0x38 // 4 bytes#define CREDIT_BALANCE_ADDR 0x42 // 4 bytes#define HOLD_ADDR 0x46 // 2 bytesboolean sound =true;byte reelMatches =0; // per play variablesbyte shipMatches =0;unsigned long wagered =0; // amount wagered on a single spindouble owedExcess =0; // change, need to track this so hold is accurateunsigned long twoMatchCount =0; // 1 if two symbols matchunsigned int threeMatchCount =0; // 1 if three symbols matchunsigned long shipOneMatchCount =0; // 1 if there's one ship presentunsigned int shipTwoMatchCount =0; // 1 if there are two ships presentunsigned int shipThreeMatchCount =0; // 1 if there are three ships present (Jackpot!)unsigned long totalCalcs =0; // total plays only relavent in auto modesigned long startingCreditBalance; // the credit balance before spinningint increment =WAGER_INCREMENT;#define DISP_CREDIT_INCREMENT 1 // on the seven segment display, increment/decrement the balance by this value until the final value is reached. // lifetime variables (stored in EEprom) Reset sets most back to zerounsigned long storedPayedOut; // sum of all payoutsunsigned long storedWagered; // sum of all wagers (profit =payouts - wagers)unsigned long storedPlays; // the number of spinsunsigned long storedTwoMatchCount; // number of times two symbols have matchedunsigned int storedThreeMatchCount; // number of times three symbols have matchedunsigned long storedShipOneMatchCount; // number of times one ship has appearedunsigned int storedShipTwoMatchCount; // number of time two ships have appearedunsigned int storedShipThreeMatchCount; // number of times three ships have appeared (Jackpot!)unsigned long storedEEpromWrites; // number of times we've written to EEprom. 100,000 is the approximate maximumsigned long storedCreditBalance; // the credit balance.int storedHold =DEFAULT_HOLD; // the house advantage, in percent, usually between 1 and 15, 2 bytes volatile byte portdhistory =0b00000100; // default is high because of the pull-up, correct settingvolatile byte portchistory =0b00001110; // default is high because of the pull-up, correct setting //- Debugging Routines // These routines are helpful for debugging, I will leave them in for your use. // For sending output to the serial monitor. Set the baud rate in setup.void debug(String text) { if (DEBUG) { Serial.println(text); }}void debugNoLF(String text) { if (DEBUG) { Serial.print(text); }}void debugInt(signed int anInt) { if (DEBUG) { char myInt[10]; itoa(anInt,myInt,10); debug(myInt); }}void debugLong(signed long aLong) { if (DEBUG) { char myLong[10]; ltoa(aLong,myLong,10); debug(myLong); }}void debugDouble(double aDouble) { if (DEBUG) { char *myDouble =ftoa(aDouble); debug(myDouble); }}void debugMetric(const char myString[], signed int anInt) { if (DEBUG) { debugNoLF(myString);debugNoLF(F(":")); debugInt(anInt); Serial.print(F("\r\n")); }}void debugMetricLong(const char myString[], signed long aLong) { if (DEBUG) { debugNoLF(myString);debugNoLF(F(":")); debugLong(aLong); Serial.print(F("\r\n")); }}void debugStoredMetrics() { for (int i =0; i <11; i++) { debug(metricsMenu[i]); }}void debugMetricDouble(const char myString[], double aDouble) { if (DEBUG) { debugNoLF(myString);debugNoLF(F(":")); debugDouble(aDouble); Serial.print(F("\r\n")); }} // quick and dirty ftoa for legacy codechar *ftoa(double f) // from https://www.microchip.com/forums/m1020134.aspx{ static char buf[17]; char * cp =buf; unsigned long l, rem; if(f <0) { *cp++ ='-'; f =-f; } l =(unsigned long)f; f -=(double)l; rem =(unsigned long)(f * 1e6); sprintf(cp, "%lu.%10.10lu", l, rem); return buf;}//- All Other Functionsvoid beep() { // Beep and flash LED green unless STATE_AUTO setGreen(); if (sound) { BUZZER_PORT |=(1 < 0) { celebrateWin(reelMatches); } setupMetricsMenu(); } else if ((totalCalcs++%EEPROM_FREQ) ==0) { // EEPROM can be written ~100,000 times, storeMetrics(); displayCredits(); // displayCredits takes care of the sign on increment setupMetricsMenu(); debugStoredMetrics(); debugMetricDouble("owedExcess",owedExcess); // don't want to put owedExcess in metricsMenu because of global var space shortage if (totalCalcs>=AUTO_MODE_MAX) { // drop out of auto mode when threshold exceeded ClearBit(machineState, STATE_AUTO); SetState(STATE_IDLE); event =EVENT_NONE; } } ClearBit(machineState, STATE_SPINNING);}void spin() {//debug("spin()"); SetState(STATE_SPINNING); if (!(STATE_AUTO ==(machineState &STATE_AUTO))) { beep(); } zeroAllBalances(); byte reelsStopped[NUMREELS] ={0,0,0}; byte stopArrayPos[NUMREELS]; for (int reelNum =0; reelNum  0) { winnings =wagered * (THREE_SPACESHIP_PAYOUT - (THREE_SPACESHIP_PAYOUT * (storedHold/100.0))); // winnings are the amount wagered times the payout minus the hold. } else if (threeMatchCount> 0) { winnings =wagered * (THREE_SYMBOL_PAYOUT - (THREE_SYMBOL_PAYOUT * (storedHold/100.0))); } else if (shipTwoMatchCount> 0) { winnings =wagered * (TWO_SPACESHIP_PAYOUT - (TWO_SPACESHIP_PAYOUT * (storedHold/100.0))); } else if (shipOneMatchCount> 0) { winnings =wagered * (ONE_SPACESHIP_PAYOUT - (ONE_SPACESHIP_PAYOUT * (storedHold/100.0))); } else if (twoMatchCount> 0) { winnings =wagered * (TWO_SYMBOL_PAYOUT - (TWO_SYMBOL_PAYOUT * (storedHold/100.0))); } else { winnings =0; } signed long roundWinnings =(signed long) round(winnings); owedExcess +=winnings - roundWinnings; // owedExcess is the change; credits between -1 and 1. if (owedExcess>=1 || owedExcess <=-1) { // if we can pay out some excess int roundOwedExcess =(int) round(owedExcess); roundWinnings +=roundOwedExcess; // add the rounded portion to the winnings owedExcess -=roundOwedExcess; // subtract out what we added to continue to track the excess } roundWinnings -=wagered; // you pay for your bet whether you won or not! // winnings -=wagered; return roundWinnings;// return((signed long) round(winnings));}void calcStored(signed long winnings) { storedPayedOut +=winnings; storedWagered +=wagered; startingCreditBalance =storedCreditBalance; storedCreditBalance +=winnings; storedPlays +=1; // calcStored is called one time per play storedTwoMatchCount +=twoMatchCount; storedThreeMatchCount +=threeMatchCount; storedShipOneMatchCount +=shipOneMatchCount; storedShipTwoMatchCount +=shipTwoMatchCount; storedShipThreeMatchCount +=shipThreeMatchCount;}void storeMetrics() { beepAuto(); // so we know we're not hung in auto mode. updateStoredPayedOut(); updateStoredWagered(); updateStoredPlays(); updateStoredTwoMatchCount(); updateStoredThreeMatchCount(); updateStoredShipOneMatchCount(); updateStoredShipTwoMatchCount(); updateStoredShipThreeMatchCount(); storedEEpromWrites++; updateStoredEEpromWrites(); updateStoredCreditBalance(); updateStoredHold();}void displayCredits() {//debug("displayCredits()"); int xmitIncrement; if ((STATE_AUTO ==(machineState &STATE_AUTO))) { // display the credits here if we're in auto mode. xmitIncrement =abs(startingCreditBalance - storedCreditBalance); // we don't want the display slave to count up/down } else { xmitIncrement =DISP_CREDIT_INCREMENT; // set increment back to what it should be during manual play } Wire.beginTransmission(CREDITS_I2C_SLAVE_ADDR); Wire.write( startingCreditBalance &0xFF); Wire.write((startingCreditBalance &0xFF00)>> 8); Wire.write((startingCreditBalance &0xFF0000)>> 16); Wire.write((startingCreditBalance &0xFF000000)>> 24); // most sigificant byte sent last if (startingCreditBalance> storedCreditBalance) { // if the player lost, xmitIncrement *=-1; // flip the sign on increment so we count down } Wire.write( xmitIncrement &0xFF); Wire.write((xmitIncrement &0xFF00)>> 8); Wire.write( storedCreditBalance &0xFF); Wire.write((storedCreditBalance &0xFF00)>> 8); Wire.write((storedCreditBalance &0xFF0000)>> 16); Wire.write((storedCreditBalance &0xFF000000)>> 24); // most sigificant byte sent last byte error =Wire.endTransmission(); if (error==4) { debug(F("Unknown error at address")); // I've never seen this happen. } }bool allReelsStopped(byte reelsStopped[]) { byte sumStopped =0; for (int i; i  
    SlotMachine.hC Header File
    const byte reel[] ={ // 0 star B10011001, //0 B01011010, B00111100, B11111111, B11111111, B00111100, B01011010, B10011001, // 1 one spot on dice B00000000, // 8 B00000000, B00000000, B00011000, B00011000, B00000000, B00000000, B00000000, // 2 three bars B11111111, // 16 B11111111, B00000000, B11111111, B11111111, B00000000, B11111111, B11111111, // 3 heart B01100110, // 24 B11111111, B11111111, B11111111, B11111111, B01111110, B00111100, B00011000, // 4 two spots on dice B00000000, // 32 B01100000, B01100000, B00000000, B00000000, B00000110, B00000110, B00000000, // 5 seven B00000000, // 40 B01111110, B01111110, B00001100, B00011000, B00111000, B00111000, B00000000, // 6 dollar sign B00011000, // 48 B00111100, B01011010, B00111000, B00011100, B01011010, B00111100, B00011000, // 7 three spots on dice B00000000, B01100000, B01100000, B00011000, B00011000, B00000110, B00000110, B00000000, // 8 inverse 9 spots, hashtag # B00100100, B00100100, B11111111, B00100100, B00100100, B11111111, B00100100, B00100100, // 9 one bar B00000000, B00000000, B00000000, B11111111, B11111111, B00000000, B00000000, B00000000, // 10 four on dice B00000000, B01100110, B01100110, B00000000, B00000000, B01100110, B01100110, B00000000, // 11 inverse seven B11111111, B10000001, B10000001, B11110011, B11100111, B11000111, B11000111, B11111111, // 12 9 spots B11011011, B11011011, B00000000, B11011011, B11011011, B00000000, B11011011, B11011011, // 13 five on dice B00000000, B01100110, B01100110, B00011000, B00011000, B01100110, B01100110, B00000000, // 14 two bars B00000000, B11111111, B11111111, B00000000, B00000000, B11111111, B11111111, B00000000, // 15 Alien 0 (120) B01000010, B00100100, B01111110, B11011011, B11111111, B11111111, B10100101, B00100100, // 16 smile face (128) B00000000, B00100100, B00000000, B00011000, B01000010, B01000010, B00111100, B00011000, // 17 6 on dice (136) B00000000, B11011011, B11011011, B00000000, B00000000, B11011011, B11011011, B00000000, // 18 SpaceShip (144) B00000000, B00000000, B00111100, B01111110, B10101011, B01111110, B00111100, B00000000, // 19 Alien 1 (152) B00011000, B00111100, B01111110, B11011011, B11111111, B00100100, B01011010, B10100101, // 20 Alien 2 (160) B00011000, B00111100, B01111110, B11011011, B11111111, B00100100, B01011010, B01000010, // 21 Alien 3 (168) B00000000, B10000001, B11111111, B11011011, B11111111, B01111110, B00100100, B01000010, // 22 one B00010000, B00110000, B00010000, B00010000, B00010000, B00010000, B00010000, B00111000, // 23 two B00111000, B01000100, B10000010, B00000100, B00001000, B00010000, B00100000, B11111110, // 24 three B11111111, // 192 B00000010, B00000100, B00011100, B00000010, B00000100, B00001000, B11100000};/************************************************* * Public Constants *************************************************/#define NOTE_B0 31#define NOTE_C1 33#define NOTE_CS1 35#define NOTE_D1 37#define NOTE_DS1 39#define NOTE_E1 41#define NOTE_F1 44#define NOTE_FS1 46#define NOTE_G1 49#define NOTE_GS1 52#define NOTE_A1 55#define NOTE_AS1 58#define NOTE_B1 62#define NOTE_C2 65#define NOTE_CS2 69#define NOTE_D2 73#define NOTE_DS2 78#define NOTE_E2 82#define NOTE_F2 87#define NOTE_FS2 93#define NOTE_G2 98#define NOTE_GS2 104#define NOTE_A2 110#define NOTE_AS2 117#define NOTE_B2 123#define NOTE_C3 131#define NOTE_CS3 139#define NOTE_D3 147#define NOTE_DS3 156#define NOTE_E3 165#define NOTE_F3 175#define NOTE_FS3 185#define NOTE_G3 196#define NOTE_GS3 208#define NOTE_A3 220#define NOTE_AS3 233#define NOTE_B3 247#define NOTE_C4 262#define NOTE_CS4 277#define NOTE_D4 294#define NOTE_DS4 311#define NOTE_E4 330#define NOTE_F4 349#define NOTE_FS4 370#define NOTE_G4 392#define NOTE_GS4 415#define NOTE_A4 440#define NOTE_AS4 466#define NOTE_B4 494#define NOTE_C5 523#define NOTE_CS5 554#define NOTE_D5 587#define NOTE_DS5 622#define NOTE_E5 659#define NOTE_F5 698 #define NOTE_FS5 740#define NOTE_G5 784#define NOTE_GS5 831#define NOTE_A5 880#define NOTE_AS5 932#define NOTE_B5 988#define NOTE_C6 1047 #define NOTE_CS6 1109#define NOTE_D6 1175#define NOTE_DS6 1245#define NOTE_E6 1319#define NOTE_F6 1397 #define NOTE_FS6 1480#define NOTE_G6 1568 #define NOTE_GS6 1661#define NOTE_A6 1760 #define NOTE_AS6 1865#define NOTE_B6 1976#define NOTE_C7 2093#define NOTE_CS7 2217#define NOTE_D7 2349#define NOTE_DS7 2489#define NOTE_E7 2637#define NOTE_F7 2794#define NOTE_FS7 2960#define NOTE_G7 3136#define NOTE_GS7 3322#define NOTE_A7 3520#define NOTE_AS7 3729#define NOTE_B7 3951#define NOTE_C8 4186#define NOTE_CS8 4435#define NOTE_D8 4699#define NOTE_DS8 4978
    slotCreditsDisplaySlave.inoArduino
    /*slotCreditsDisplaySlave.ino Version:1.0 Date:2018/07/01 - 2018/07/29 Device:ATMega328P-PU @ 16mHz Language:C Purpose =======`The .purpose of this program is to function as an I2C slave responsible for displaying credits in a slot machine Known Defects =============- TODO ====- is 38400 an efficient baud rate for arduino running at 16mhz? - include a 100 ohm resistor with the piezo buzzer - is 100kHz the fastest setting we can accomodate w/ Wire library? Warnings ========- Suggestions ===========- Author ======- Copyright 2018, Daniel Murphy  License =======Daniel J. Murphy hereby disclaims all copyright interest in this program written by Daniel J. Murphy. 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 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 . Libraries =========- https://github.com/wayoda/LedControl The Program ===========- Includes */#include #include "LedControl.h"#define BAUD_RATE 38400 #define CREDITS_SLAVE_ADDR 16 #define DISPLAY_DELAY 5#define DEBUG 1#define BUZZER_DDR DDRB#define BUZZER_PORT PORTB#define BUZZER_PIN DDB1#define TONE_PIN 9 // Pin you have speaker/piezo connected to (be sure to include a 100 ohm resistor).#define BEEP_LENGTH 100 // Now we need a LedControl to work with. // pin 12 is connected to the DataIn // pin 11 is connected to the CLK // pin 10 is connected to LOAD // We have only a single MAX72XX.LedControl lc=LedControl(12,11,10,1);static const int slaveAddress =CREDITS_SLAVE_ADDR; long volatile theCredits[10] ={0L,0L,0L,0L,0L,0L,0L,0L,0L,0L};signed long volatile displayedBalance =0;signed long volatile startingCreditBalance =0;signed long volatile endingCreditBalance;signed int volatile increment;boolean volatile updateDisplayFlag =false;void debug(String text) { if (DEBUG) { Serial.println(text); }}void debugNoLF(String text) { if (DEBUG) { Serial.print(text); }}void debugInt(signed int anInt) { if (DEBUG) { char myInt[10]; itoa(anInt,myInt,10); debug(myInt); }}void debugLong(signed long aLong) { if (DEBUG) { char myLong[10]; ltoa(aLong,myLong,10); debug(myLong); }}void debugMetric(const char myString[], signed int anInt) { if (DEBUG) { debugNoLF(myString);debugNoLF(":"); debugInt(anInt); Serial.print("\r\n"); }}void debugMetricLong(const char myString[], signed long aLong) { if (DEBUG) { debugNoLF(myString);debugNoLF(":"); debugLong(aLong); Serial.print("\r\n"); }}void beep() { BUZZER_PORT |=(1 <  

    회로도

    slotmachine_1nXzMvYVPH.fzzThis spreadsheet was used to prove that the payout table is correct. Sheet password is "password". slotpayouttablecalc_v1_1_SfcpHOBOvf.xlsx
    Close Encounters Slot Machine
    link to files on Fritzing.orgSchematics on Fritzing.org The Fritzing Schematic

    제조공정

    1. EEG 기계
    2. 자판기
    3. 투표기
    4. 기계 교환
    5. EKG 기계
    6. 재봉틀
    7. 선반 기계의 부품
    8. 선반 기계의 이해
    9. 밀링 머신의 구성 요소
    10. 기계의 이해