Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Mesin Slot Bertema ATMmega Alien

Komponen dan persediaan

Teknologi Microchip ATmega328
ATmega328P-PU, tepatnya.$3.00 Satu untuk SlotMachine, satu untuk tampilan LED kredit I2C budak.
× 2
Tampilan Tujuh Segmen dengan 8 digit
$1,20 Untuk menampilkan saldo kredit pemain.
× 1
matriks 8x8, 4 segmen, MAX7219
$3,78 Untuk mensimulasikan gulungan yang berputar dan menampilkan simbol. Hanya tiga dari empat segmen yang digunakan.
× 1
Modul LCD Lampu Latar Biru Seri I2C 2004 20 X 4 2004
$3.00 Untuk menampilkan menu opsi. Berbelanja di aliexpress. Jangan membayar ongkos kirim!
× 1
Breadboard (generik)
830 poin$4.00
× 2
Tombol Kontak Sesaat
$1,00 untuk 50. Satu mengontrol pemintalan gulungan, tiga untuk menavigasi menu, dua untuk grounding pin 1 dari ATmegas.
× 6
Katoda Umum Difusi RGB
Digunakan untuk menandakan berbagai hal.
× 1
LED (generik)
Menunjukkan jika daya disuplai ke papan.
× 1
Resistor 10k ohm
4 untuk menarik setiap tombol, 2 untuk pin 1 ATmegas.
× 6
Resistor 1k ohm
Antara setiap tombol dan pin input ATmega.
× 4
Resistor 330 ohm
Untuk lead merah, hijau dan biru dari LED RGB.
× 3
Kristal 16 MHz
Satu untuk ATmega328P-PU SlotMachine, dan satu lagi untuk ATmega328P-PU budak tampilan LED. Keduanya berjalan pada 16MHz.
× 2
Sakelar Geser
Untuk catu daya.
× 1
Buzzer
Dua diperlukan, satu untuk chip SlotMachine, dan satu untuk chip slave tampilan. Akan lebih baik untuk memodifikasi sirkuit sehingga hanya satu yang diperlukan dan dapat digunakan bersama oleh kedua pengontrol mikro.
× 2
Kapasitor 22 pF
× 4
0,10 uF Kapasitor
× 6
Kapasitor 100 nF
Ini opsional dan hanya diperlukan jika Anda menggunakan adaptor serial USB Mini Arduino untuk memprogram SlotMachine chip, seperti yang saya miliki.
× 1
Kapasitor 10 F
Untuk membantu memperlancar tegangan suplai.
× 2
Regulator Linier (7805)
Untuk mengatur suplai tegangan, 5V.
× 1
Kabel jumper (generik)
Anda akan membutuhkan banyak. Sebagian besar saya buat sendiri, tetapi saya juga menggunakan kabel jumper.
× 1
Suatu catu daya 5v
× 1
Adaptor serial USB Mini Arduino
$13.20 Ini opsional, Anda dapat menggunakan Arduino Uno untuk memprogram chip ATmega 328p-pu.
× 1
Adaptor Serial USB ke TTL FTDI
$1,66 x 2 =$3,32 Untuk memprogram ATmega328P-PU di tempatnya. Tidak digambarkan dalam skema.
× 1
Breadboard yang dapat disolder
Breadboard yang dapat disolder ukuran penuh.
× 1
Breadboard Dapat Disolder SparkFun - Mini
× 1
Pocket Solder- 60/40 Rosin Core 0.031" diameter
× 1
Lampiran Kotak Proyek Elektronik Tahan Air Plastik Bening
$13.00 Ini adalah penutupnya.
× 1

Alat dan mesin yang diperlukan

Besi solder (generik)
Tangan Bantuan

Aplikasi dan layanan online

Arduino IDE
Perpustakaan Nada Bebas Timer
Pustaka Kontrol LED
LiquidCrystal/LCD Library
LiquidCrystal I2C Library

Tentang proyek ini

Mesin Slot Bertema ATmega Alien

Proyek ini adalah implementasi saya dari mesin slot bertema alien menggunakan dua mikrokontroler ATmega328P-PU. Saya terinspirasi oleh Mesin Slot Invasi Alien Cory Potter, dan saya ingin memperluas ide itu. Mesin slot hanya untuk tujuan hiburan dan pendidikan. Saya mencoba yang terbaik untuk membuat permainan mensimulasikan mesin slot nyata sedekat mungkin. Proyek ini saat ini sedang dalam proses. Enklosur akan ditambahkan segera setelah suku cadang tiba dari China dan saya memiliki kesempatan untuk menyolder semuanya. Proyek ini memakan waktu sekitar dua bulan bagi saya untuk membangun di waktu luang saya. Bagian tersulit dari pembuatannya bagi saya adalah memahami semua matematika yang terlibat dalam membuat permainan berperilaku seperti yang diharapkan industri kasino dari mesin slot sederhana yang akan berperilaku setelah setengah miliar atau lebih simulasi.

Cara Kerja Game

Gim ini memiliki tiga gulungan dengan 25 simbol unik yang sama yang muncul di setiap gulungan (salah satu dari matriks 8x8 pada komponen dengan 4 matriks 8x8 tidak digunakan.) Ada lima cara berbeda untuk menang. Jika Anda mendapatkan tiga pesawat ruang angkasa, Anda memenangkan jackpot. Jika Anda mendapatkan satu atau dua pesawat ruang angkasa, Anda juga memenangkan beberapa kredit. Jika Anda mendapatkan dua atau tiga simbol yang cocok, Anda juga menang. Jika Anda mendapatkan pesawat luar angkasa dan dua simbol yang cocok, seperti yang digambarkan di bawah ini, permainan membayar berdasarkan acara yang menang dengan probabilitas terendah/pembayaran tertinggi; dengan kata lain memenangkan acara saling eksklusif, Anda tidak dapat memenangkan dua cara berbeda dalam satu putaran gulungan. Ini membuat pemrograman sedikit lebih sederhana. Ada banyak tantangan lain bagi saya.

Fitur

Mesin slot ini memiliki beberapa fitur menarik yang dapat diakses melalui layar LCD berkemampuan 20 x 4 I2C menggunakan dua tombol navigasi dan tombol pilih. Tombol menggunakan algoritme de-bouncing yang cukup canggih yang memanfaatkan kemampuan interupsi eksternal pengontrol mikro. Ini adalah menu utamanya.

Karena ada enam baris dalam menu, Anda harus menggulir ke bawah menggunakan tombol 'navigasi ke bawah' untuk melihat seluruh menu. Ada tombol yang didedikasikan untuk 'memutar' gulungan. Selain itu Anda juga dapat memilih 'Play' dari menu utama. Anda dapat mengubah taruhan Anda kapan saja.

Fitur yang paling menarik adalah game ini dapat dimainkan dalam mode 'otomatis'; yaitu Anda memilih opsi mode otomatis dari menu pengaturan di layar LCD dan permainan diputar berulang-ulang hingga Anda memilih opsi lagi atau 1 juta permainan telah terjadi. Ini adalah fungsi penting untuk menguji permainan. Anda juga dapat menonaktifkan suara di sini.

Melalui menu pada LCD, Anda juga dapat melihat semua metrik yang dihasilkan dari simulasi. Metrik ini juga merupakan keluaran dan dapat dilihat di monitor serial jika Anda menghubungkan mikrokontroler ke monitor melalui pin RX dan TX menggunakan kabel USB. Daftar metrik yang ditampilkan mencakup saldo kredit Anda, berapa kali Anda mendapatkan jackpot, dan berapa kali Anda memenangkan kredit dengan cara lain. Ini memungkinkan saya untuk menjalankan simulasi berdasarkan berbagai pembayaran, dan berguna untuk membuat dan membuktikan tabel pembayaran. Tabel pembayaran itu sendiri tidak dapat dikonfigurasi; setelah diatur itu harus tetap sama. Saya kira adalah mungkin untuk membuat indeks volatilitas dapat dikonfigurasi dengan menggunakannya untuk menggerakkan tabel pembayaran, tetapi itu akan membutuhkan lebih banyak pekerjaan.

Opsi Reset memungkinkan Anda untuk menyetel ulang semua metrik (kecuali penulisan EEprom), kembali ke nol. Chip akan bekerja selama sekitar 100.000 penulisan ke EEprom. Karena ada 512k EEprom yang tersedia di chip, dan kami hanya menggunakan sebagian kecil dari itu, akan memungkinkan untuk benar-benar memindahkan lokasi metrik di EEprom saat kami mendekati 100.000 penulisan. Saya belum menerapkan fitur ini tetapi ini akan menjadi sarana untuk memperpanjang umur chip.

Akhirnya, penahanan, atau persentase dari setiap taruhan yang disimpan oleh rumah (dari waktu ke waktu), dapat dikonfigurasi. Ingatlah bahwa setelah melakukan operasi Reset, penahanan perlu disetel lagi.

Saldo kredit pemain selalu ditampilkan dalam tampilan tujuh segmen delapan digit.

Matematika

Banyak pekerjaan yang dilakukan untuk memastikan bahwa permainan itu realistis. Probabilitas dihitung dan tabel pembayaran dirancang agar permainan memiliki Indeks Volatilitas (VI) yang dapat diterima. Indeks ini mengukur seberapa dapat diprediksi perilaku mesin. Sebuah mesin dengan VI yang lebih tinggi lebih mungkin untuk membuat pemain (atau rumah) lebih banyak uang. Ini kurang dapat diprediksi daripada mesin dengan VI lebih rendah. Memang benar bahwa permainan yang sama persis akan ada di kasino yang berbeda (atau bahkan kasino yang sama) dengan VI yang berbeda. VI diubah dengan memanipulasi jadwal pembayaran. Untuk permainan kami, berikut adalah probabilitas dan pembayaran untuk setiap jenis kemenangan.

Perhatikan bahwa peluang (paling kanan) dan pembayaran (paling kiri) sangat berbeda. Jika permainan ini diprogram sehingga tabel pembayaran cocok atau mengikuti peluang dengan cermat, VI-nya akan sangat tinggi. Penangguhan dihitung sebagai persentase pembayaran, dan merupakan bagian dari taruhan yang disimpan oleh rumah/kasino. Seperti yang dinyatakan, Anda dapat mengatur penahanan melalui menu LCD. Ingatlah bahwa yurisdiksi yang berbeda memiliki peraturan berbeda yang mengatur penahanan maksimum untuk mesin slot di yurisdiksi itu. Penahanan maksimum tipikal adalah 15%. Pahami bahwa menyetel penahanan ke maksimum yang diizinkan oleh hukum tidak serta merta memaksimalkan keuntungan yang dihasilkan oleh mesin itu, karena penahanan yang lebih tinggi mungkin membuat pemain enggan menggunakan mesin. Saya menduga, bagaimanapun, bahwa banyak pemain mengabaikan penahanan, yang biasanya terkubur dalam cetakan halus, dan kurva permintaan untuk mesin relatif vertikal (artinya biaya penggunaan mesin, penahanan, sebagian besar diabaikan), dan bahwa keuntungan yang dihasilkan oleh mesin jauh lebih tergantung pada lokasi atau penempatan mesin serta desain permainan itu sendiri. Tapi itu hanya spekulasi. Saya yakin ada beberapa penjudi cerdas di luar sana yang sensitif terhadap penangguhan.

Spreadsheet, tersedia dengan kode, dengan tiga tabel dibuat untuk membuktikan bahwa game bekerja dengan benar (tabel pertama muncul di atas). Langkah pertama dalam membangun spreadsheet adalah menghitung secara akurat peluang setiap jenis kemenangan (kolom Probabilitas Terhitung).

Tiga Pesawat Luar Angkasa

Peluang munculnya tiga pesawat luar angkasa adalah kebalikan dari jumlah kombinasi yang mungkin. Jumlah kombinasi pemenang, satu, di atas jumlah total kombinasi yang mungkin, 15625. Ada 25 simbol unik pada setiap gulungan, jadi kemungkinannya adalah 1 / (25 x 25 x 25), atau 0,000064. Itu membuat peluang, 1/probabilitas - 1, sama dengan 1 hingga 15624. Saya belajar cara menghitung peluang dari probabilitas di sini.

Pertandingan Tiga Simbol (kecuali pesawat luar angkasa)

Probabilitas bahwa tiga simbol, selain pesawat ruang angkasa, akan cocok adalah 24 (jumlah simbol unik pada setiap gulungan dikurangi pesawat ruang angkasa) dibagi dengan jumlah kemungkinan kombinasi. 24 adalah pembilang karena ada 24 kombinasi dari tiga simbol yang cocok. 24/15625 =0,001536. Itu membuat peluangnya sekitar 1 hingga 650,04.

Dua Pesawat Luar Angkasa

Ada 24 x 3 kombinasi total dua pesawat ruang angkasa yang cocok. Itu karena ada cara untuk membuat dua korek api dari pesawat ruang angkasa. Berikan X =pesawat ruang angkasa dan Y =simbol lainnya, XXY, XYX, dan YXX. Ada 24 kemungkinan nilai untuk Y. Jadi 24 X 3 / 15625 =0,004608. Peluangnya adalah 1 banding 216,01.

Satu Pesawat Luar Angkasa Muncul

Untuk setiap gulungan ada 24 x 24 kombinasi yang mungkin untuk satu pesawat ruang angkasa yang muncul.

Sebuah pesawat ruang angkasa dapat muncul di gulungan apa pun, jadi Anda perlu mengalikan jumlah kombinasi yang tersedia pada satu gulungan dengan tiga gulungan. Jadi peluangnya adalah 24 x 24 x 3 / 15625 =0,110592. Peluangnya adalah 1 hingga 8,04.

Dua Simbol Cocok

Untuk dua simbol yang diberikan, kecuali pesawat ruang angkasa, ada 23 (25 dikurangi satu pesawat ruang angkasa dikurangi satu simbol yang akan membuatnya menjadi tiga simbol yang cocok) x 3 gulungan x 24 simbol yang bukan merupakan pesawat ruang angkasa. Probabilitasnya adalah (23 X 3 X 24)/15625 =0.105984. Peluangnya adalah 1 hingga 8,44.

Sekarang saya memiliki probabilitas untuk setiap jenis kemenangan, saya dapat menggunakan spreadsheet untuk merancang tabel pembayaran dengan cara yang membuat indeks volatilitas dapat diterima (<~20). Untuk memahami bagaimana melakukan ini, saya sangat bergantung pada posting ini. Saya memasukkan nilai di kolom Pendapatan Rumah dari tabel pertama, menggunakan proses coba-coba, hingga VI di bawah 20 dan Total di sel J10 mendekati nol yang saya bisa dapatkan. Dengan menggunakan nilai-nilai itu, saya menetapkan THREE_SPACESHIP_PAYOUT, THREE_SYMBOL_PAYOUT, TWO_SPACESHIP_PAYOUT, ONE_SPACESHIP_PAYOUT, dan TWO_SYMBOL_PAYOUT di SlotMachine.ino. Kemudian, pertama dengan menggunakan penahan nol persen, saya menjalankan lima simulasi dari 1.000, 001 pemutaran, dan memasukkan nilai dari menu metrik ke dalam baris dan kolom yang sesuai di tabel Hasil Aktual (tabel ketiga).

Saya mengamati bahwa Probabilitas Aktual dilacak erat dengan probabilitas Terhitung, dan bahwa kolom Prob Diff Pct masuk akal. Saya juga mencocokkan nilai di baris House Pays ke atas dengan rentang nilai dari kolom Penghasilan Tinggi dan Penghasilan Rendah dari baris 1.000, 000 pada tabel Memahami Potensi Penghasilan (tabel kedua), dan mengamati bahwa nilai dari tabel Hasil Aktual berada di dalam kisaran yang ditentukan oleh kolom Pendapatan Tinggi dan Pendapatan Rendah. Tabel Memahami Potensi Pendapatan mendefinisikan kisaran pendapatan yang diharapkan untuk nilai penahanan tertentu dengan interval kepercayaan 90%. Dalam contoh di bawah ini, penahanan diatur ke 0, sehingga kemungkinan menang cocok dengan kemungkinan kalah. Jika Anda memainkan game 1 juta kali, ada kemungkinan 90% bahwa Penghasilan akan berada di antara 16, 432 dan - 16, 432.

Setelah bekerja dengan spreadsheet dan program dan menjalankan jutaan simulasi, saya dapat mengatasi cacat pada program, mengatasi cacat pada spreadsheet, dan menentukan nilai untuk tabel pembayaran yang mempertahankan VI <20. Akhirnya saya mengubah penangguhan hingga 15% dan menjalankan serangkaian 5 simulasi untuk memverifikasi bahwa pendapatan game sesuai dengan harapan jika akan diterapkan dalam situasi dunia nyata Berikut adalah tabel pendapatan untuk penangguhan 15%.

Dan inilah hasil sebenarnya.

Jika Anda ingin benar-benar memahami semua matematika di balik pengaturan nilai pembayaran, saya mendorong Anda untuk memeriksa rumus di spreadsheet. Jika Anda menemukan kesalahan, tunjukkan kepada saya; Saya bukan ahli matematika (atau programmer C) berdasarkan perdagangan, jadi penafian standar berlaku.

Kode

Saya tidak akan membawa Anda melalui kode baris demi baris. Ini banyak dikomentari dan tidak ada yang rumit terjadi di mana pun. Jadi gunakan Force, baca sumbernya. Jika Anda tidak terbiasa dengan manipulasi register pada ATmega386 dan ingin memahami lebih lanjut tentang cara menulis kode untuk mikrokontroler AVR tanpa bergantung pada perpustakaan Arduino, saya sarankan Anda untuk mendapatkan salinan Elliott William's buku yang sangat bagus, "Membuat:Pemrograman AVR". Jika Anda kebetulan berlangganan safaribooksonline.com, Anda akan menemukannya di sana. Jika tidak, itu tersedia di sini di Amazon. Dalam program ini saya menggunakan fungsi Arduino di beberapa tempat, dan di tempat lain saya memanipulasi register secara langsung. Maaf soal itu.

Hal pertama yang mungkin Anda perhatikan adalah bahwa program ini menggunakan variabel global secara ekstensif. Ada diskusi bagus tentang topik ini di Stack Overflow. Saya tidak akan mempromosikan atau membela penggunaan berat variabel global di sini, tetapi saya akan mendorong Anda untuk memahami semua perspektif tentang topik dan menyadari bahwa ada argumen yang kuat untuk menggunakannya pada proyek aplikasi tertanam dengan programmer tunggal dan sumber daya yang terbatas. .

Saya memang menggunakan beberapa perpustakaan, yang tanpanya proyek ini tidak mungkin bagi saya. Perpustakaan Nada Bebas Timer digunakan untuk menggerakkan berbagai frekuensi melalui speaker piezo pasif. Di SlotMachine.h Anda akan melihat bahwa ada banyak definisi untuk not musik. Anda dapat menggunakannya untuk menyusun melodi apa pun yang Anda inginkan. Saya hanya menggunakan beberapa dari mereka untuk memainkan bagian dari tema dari "Close Encounters of the Third Kind" ketika mikrokontroler SlotMachine dimulai dan fungsi pengaturan berjalan. Saya memilih perpustakaan timer gratis karena saya pikir saya akan membutuhkan timer untuk sesuatu, tapi akhirnya saya tidak menggunakan timer sama sekali. Ini tersedia jika Anda membutuhkannya. Pustaka Kontrol LED digunakan di SlotMachine.ino dan slotCreditDisplaySlave.ino. Yang pertama digunakan untuk mengontrol tiga matriks LED 8 x 8 yang berfungsi sebagai gulungan mesin slot. Di slotCreditDisplaySlave.ino perpustakaan memfasilitasi akses ke tampilan tujuh segmen 8 digit yang menampilkan saldo kredit pemain. Ini akan menjadi saat yang tepat untuk menyebutkan bahwa saya mencoba untuk menghindari menggunakan chip AVR lain (ATmega328) hanya untuk melayani saldo kredit, tetapi saya tidak dapat menemukan cara untuk mengontrol matriks 8 x 8 dan tampilan tujuh segmen 8 digit dari mikrokontroler tunggal. Jadi pada akhirnya saya harus membuat budak I2C untuk melayani tujuan itu. Sudah pasti bahwa Anda dapat menggunakan AVR yang lebih murah untuk melakukan tugas menampilkan saldo kredit, tetapi untuk menjaga hal-hal sederhana untuk artikel ini saya memilih untuk menggunakan chip ATmega328P-PU lain. Sisi baiknya, ketika Anda memenangkan jackpot besar, kredit terus dihitung pada budak tampilan kredit sementara Anda dapat melanjutkan dan berputar lagi. Pustaka LiquidCrystal/LCD dan LiquidCrystal I2C diperlukan untuk memfasilitasi akses ke layar LCD 20 baris x 4 baris. Seperti yang disebutkan, Anda dapat mengganti LCD 20 x 2 jika hanya itu yang Anda miliki, hanya dengan mengubah definisi LCD_SCREEN_HEIGHT dari 4 menjadi 2. Pastikan bahwa layar LCD yang Anda peroleh untuk proyek ini mampu I2C. Jika tidak, Anda harus memperoleh modul port papan antarmuka serial I2C SPI untuk pelat adaptor LCD1602, nomor komponen PCF8574, yang digambarkan di bawah, dan menyoldernya ke layar LCD1602 Anda.

Gim dapat berada di sejumlah status berbeda pada saat yang sama, dan variabel machineState melacak status tersebut. Misalnya, bisa 'berputar' dan dalam 'mode otomatis' secara bersamaan. Saya tidak terlalu menggunakan konsep ini di dalam program; tidak sebanyak yang saya miliki di program lain. Tetapi ada beberapa percabangan bersyarat berdasarkan negara bagian. Ada juga konsep acara, dan acara dikirim dan ditangani dalam fungsi ProcessEvents. Mungkin akan lebih baik jika ada antrian acara, tapi saya tidak melakukannya sejauh itu.

Ada daftar cacat yang diketahui dan 'yang harus dilakukan' di bagian komentar SlotMachine.ino. Terkadang ketika Anda 'memutar' gulungan (dengan menekan tombol putar atau memilih opsi 'Mainkan' dari menu LCD) satu atau bahkan dua gulungan tidak bergerak. Itu karena generator nomor acak di belakang layar memilih simbol yang sudah ditampilkan untuk gulungan itu. Ini bisa diperbaiki untuk membuat permainan tampak lebih realistis, tapi itu tidak benar-benar cacat. Gulungan tidak selesai berputar dari kiri ke kanan, seperti yang terjadi pada kebanyakan mesin slot. Hal ini dilakukan dengan desain, untuk menjaga hal-hal sederhana. Adalah mungkin untuk membuat gulungan selesai berputar dari kiri ke kanan dengan mengurutkan tiga angka acak yang dihasilkan untuk setiap putaran dalam urutan menaik sebelum gulungan benar-benar berputar, dan saya tidak peduli.

Sejauh 'todos', saya di beberapa titik ingin menambahkan perlindungan coklat dan perlindungan anjing, hanya untuk melalui latihan dan belajar bagaimana melakukannya. Perhatikan bahwa 80% dari ruang yang dialokasikan untuk variabel global sudah digunakan. Ini adalah titik di mana hal-hal dapat mulai menjadi tidak stabil dengan program ATmega386 dan Arduino. Kami berada di titik itu dengan program ini. Saya harus melakukan penganggaran agar semuanya tetap berfungsi, dan saya tidak akan merekomendasikan menambahkan global lagi ke program. Ini akan mempersulit untuk menambahkan lebih banyak fungsionalitas ke bagian Pengaturan menu, misalnya, karena menu menghabiskan banyak ruang variabel global. Saya memang mencoba memecahkan masalah variabel global dengan memindahkan menu ke memori program, tetapi saya tidak bisa mendapatkannya untuk mengurangi ruang yang digunakan oleh global, saya pikir karena kompiler perlu mengalokasikan semua ruang untuk menu bagaimanapun juga . Lebih banyak pekerjaan dapat dilakukan untuk sedikit membumbui permainan; Saya dapat menggunakan lebih banyak LED RGB dan bel piezo, merayakan kemenangan sedikit lebih banyak, mungkin membuat suara yang lebih baik saat uang hilang, tetapi saya akan menyerahkannya kepada siapa saja yang ingin memainkannya.

Saya harus mendesain semua simbol untuk permainan. Beberapa dari mereka akan mengingatkan Anda pada game arcade klasik 'Space Invaders', dan saya mungkin meminjamnya dari suatu tempat. Sisanya saya rancang dengan tangan, dan beberapa di antaranya terlihat kurang profesional. Saya menggunakan situs ini untuk membantu mendesain simbol. Jika Anda ingin menyesuaikan simbol, Anda dapat melakukannya di SlotMachine.h, dan memainkannya sesuka hati Anda. Itu tidak akan mempengaruhi logika program. Untuk simbol saya mewakili angka dalam basis 2 / biner sehingga Anda dapat mendesainnya dengan editor teks Anda.

Kode tersedia di sini di GitHub.

Membangun Mesin Slot

Saya menggunakan FTDI USB to serial board untuk memprogram kedua mikrokontroler ATmega328P-PU di tempat. Koneksi ini tidak digambarkan dalam skema Fritzing. Untuk instruksi tentang pengaturan papan pemutus FTDI pada papan tempat memotong roti tanpa solder Anda, ikuti tautan ini. Anda mungkin perlu sedikit googling untuk memahami pengaturannya. Saya percaya posting ini juga membantu saya memecahkan masalah yang saya coba untuk membuat pengontrol mikro mengatur ulang secara otomatis pada awal pemrograman melalui papan breakout FTDI. Ingatlah untuk menempatkan kapasitor 100 nF secara seri dengan koneksi antara pin reset ATmega328 (posisi 1/PC6/pin reset) dan RTS pada papan break out FTDI sehingga Anda tidak perlu menekan tombol reset saat diinginkan untuk memprogram chip. Jika Anda memilih untuk menggunakan Arduino Uno Anda untuk memprogram chip, instruksi dapat ditemukan di sini. Jika Anda hanya akan memprogram chip sekali dengan kode yang disediakan, mungkin yang tercepat dan termudah adalah memprogramnya dari Arduino Uno.

Kedua mikrokontroler diatur dengan chip 'Arduino' (ATmega328P-PU) pada papan tempat memotong roti. 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

Summary

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.

Kode

  • 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; bahkan tanpa jaminan tersirat tentang KELAYAKAN DIPERDAGANGKAN atau KESESUAIAN UNTUK TUJUAN TERTENTU. 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 Tw o 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 r ate 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 DDC 2 // 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 B ET_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; bahkan tanpa jaminan tersirat tentang KELAYAKAN DIPERDAGANGKAN atau KESESUAIAN UNTUK TUJUAN TERTENTU. 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 <  

Skema

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

Proses manufaktur

  1. Mesin EEG
  2. Mesin Penjual Otomatis
  3. Mesin Pemungutan Suara
  4. Ganti Mesin
  5. Mesin EKG
  6. Mesin Jahit
  7. Bagian dari mesin bubut
  8. Pengertian mesin bubut
  9. Komponen mesin penggilingan
  10. Memahami Mesin