+
Hardware Profile Feed

Проект неимоверно дешевой миди клавиатуры на 61 клавишу

Нам понадобятся:

ATMEGA2560 = 6$ Aliexpress

https://ru.aliexpress.com/item/1978273967.html?spm=a2g0s.8937518.0.0.33202e0eEBEFAQ

Детский синтезатор с 61 кнопками = 15$

https://ru.aliexpress.com/item/32904347680.html?spm=a2g0s.8937518.0.0.33202e0eEBEFAQ

программатор для ATMEGA = 2$

https://ru.aliexpress.com/item/32703554356.html?spm=a2g0o.productlist.0.0.4d821633lJONVY&algo_pvid=78f972c7-a478-4bff-880e-0dafe55be55f&algo_expid=78f972c7-a478-4bff-880e-0dafe55be55f-1&btsid=f7acb0bf-5f3e-479d-b9b0-c546ecf82120&ws_ab_test=searchweb0_0,searchweb201602_1,searchweb201603_53

плата для припайки атмеги = 2$

https://ru.aliexpress.com/item/32657825043.html?spm=a2g0o.productlist.0.0.33055196kx9Kui&algo_pvid=94cebf30-7305-400f-84fb-44c4f2182d68&algo_expid=94cebf30-7305-400f-84fb-44c4f2182d68-2&btsid=79c40c43-a1fd-48dd-b8df-b661cec90e44&ws_ab_test=searchweb0_0,searchweb201602_1,searchweb201603_53

блок питания на 5В = 4$

мелочевка на пару баксов

провода

паяльник

AVRSTUDIO

PROTEUS

Шарить в программировании))

Фрагмент кода на 8 клавиш

#define _ASSERT_ENABLE_

#include <string.h>

#include "compiler.h"

/**

 * \def BUFFER_SIZE

 * \brief The size of the UART buffer

 */

#define BUFFER_SIZE 20

// set the correct BAUD and F_CPU defines before including setbaud.h

#include "conf_clock.h"

#include "conf_uart.h"

/**

 * \name avr_libc_inc avr libc include files

 * @{

 */

#include <util/setbaud.h>

#include <avr/interrupt.h>

//! @}

#include "ring_buffer.h"

// buffers for use with the ring buffer (belong to the UART)

uint8_t out_buffer[BUFFER_SIZE];

uint8_t in_buffer[BUFFER_SIZE];

uint8_t chan=0;

uint8_t onchan=0x90;

uint8_t offchan=0x80;

// the string we send and receive on UART

const char test_string[] = "Kingdom MIDI Board^^!";

//! ring buffer to use for the UART transmission

struct ring_buffer ring_buffer_out;

//! ring buffer to use for the UART reception

struct ring_buffer ring_buffer_in;

/**

 * \brief UART data register empty interrupt handler

 *

 * This handler is called each time the UART data register is available for

 * sending data.

 */

ISR(UART0_DATA_EMPTY_IRQ)

{

// if there is data in the ring buffer, fetch it and send it

if (!ring_buffer_is_empty(&ring_buffer_out)) {

UDR0 = ring_buffer_get(&ring_buffer_out);

}

else {

// no more data to send, turn off data ready interrupt

UCSR0B &= ~(1 << UDRIE0);

}

}

/**

 * \brief Data RX interrupt handler

 *

 * This is the handler for UART receive data

 */

ISR(UART0_RX_IRQ)

{

ring_buffer_put(&ring_buffer_in, UDR0);

}

/**

 * \brief Initialize the UART with correct baud rate settings

 *

 * This function will initialize the UART baud rate registers with the correct

 * values using the AVR libc setbaud utility. In addition set the UART to

 * 8-bit, 1 stop and no parity.

 */

static void uart_init(void)

{

#if defined UBRR0H

// get the values from the setbaud tool

UBRR0H = UBRRH_VALUE;

UBRR0L = UBRRL_VALUE;

#else

#error "Device is not supported by the driver"

#endif

#if USE_2X

UCSR0A |= (1 << U2X0);

#endif

// enable RX and TX and set interrupts on rx complete

UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);

// 8-bit, 1 stop bit, no parity, asynchronous UART

UCSR0C = (1 << UCSZ01) | (1 << UCSZ00) | (0 << USBS0) |

(0 << UPM01) | (0 << UPM00) | (0 << UMSEL01) |

(0 << UMSEL00);

// initialize the in and out buffer for the UART

ring_buffer_out = ring_buffer_init(out_buffer, BUFFER_SIZE);

ring_buffer_in = ring_buffer_init(in_buffer, BUFFER_SIZE);

}

/**

 * \brief Function for putting a char in the UART buffer

 *

 * \param data the data to add to the UART buffer and send

 *

 */

static inline void uart_putchar(uint8_t data)

{

// Disable interrupts to get exclusive access to ring_buffer_out.

cli();

if (ring_buffer_is_empty(&ring_buffer_out)) {

// First data in buffer, enable data ready interrupt

UCSR0B |=  (1 << UDRIE0);

}

// Put data in buffer

ring_buffer_put(&ring_buffer_out, data);

// Re-enable interrupts

sei();

}

static inline void noteon(uint8_t data)

{

// Disable interrupts to get exclusive access to ring_buffer_out.

cli();

if (ring_buffer_is_empty(&ring_buffer_out)) {

// First data in buffer, enable data ready interrupt

UCSR0B |=  (1 << UDRIE0);

}

// Put data in buffer

ring_buffer_put(&ring_buffer_out, onchan);

ring_buffer_put(&ring_buffer_out, data);

ring_buffer_put(&ring_buffer_out, 0x7F);

// Re-enable interrupts

sei();

}

static inline void noteoff(uint8_t data)

{

// Disable interrupts to get exclusive access to ring_buffer_out.

cli();

if (ring_buffer_is_empty(&ring_buffer_out)) {

// First data in buffer, enable data ready interrupt

UCSR0B |=  (1 << UDRIE0);

}

// Put data in buffer

ring_buffer_put(&ring_buffer_out, offchan);

ring_buffer_put(&ring_buffer_out, data);

ring_buffer_put(&ring_buffer_out, 0x7F);

// Re-enable interrupts

sei();

}

/**

 * \brief Function for getting a char from the UART receive buffer

 *

 * \retval Next data byte in recieve buffer

 */

static inline uint8_t uart_getchar(void)

{

return ring_buffer_get(&ring_buffer_in);

}

/**

 * \brief Function to check if we have a char waiting in the UART receive buffer

 *

 * \retval true if data is waiting

 * \retval false if no data is waiting

 */

static inline bool uart_char_waiting(void)

{

return !ring_buffer_is_empty(&ring_buffer_in);

}

/**

 * \brief The main application

 *

 * This application will initialize the UART, send a character and then receive

 * it and check if it is the same character as was sent.

 *

 * \note The RX and TX pins should be externally connected in order to pass the

 * test.

 */

int main(void)

{

uint8_t data;

uint8_t cnt;

uint8_t i;

uint8_t sta=0xFF, stb=0xFF, stc=0xFF, std=0xFF, ste=0x00, stf=0xFF, stg=0xFF, sth=0xFF, stj=0xFF, stk=0xFF, stl=0x00; 

uint8_t pra=0xFF, prb=0xFF, prc=0xFF, prd=0xFF, pre=0x00, prf=0xFF, prg=0xFF, prh=0xFF, prj=0xFF, prk=0xFF, prl=0x00;

uint8_t rta=0xFF, rtb=0xFF, rtc=0xFF, rtd=0xFF, rte=0x00, rtf=0xFF, rtg=0xFF, rth=0xFF, rtj=0xFF, rtk=0xFF, rtl=0x00;

char test_string1[] = "Hi1^^!";

char test_string2[] = "Hi2^^!";

PORTA=0xFF;

DDRA=0x00;//0

PORTB=0xFF;

DDRB=0x00;//1

PORTC=0xFF;

DDRC=0x00;//2

PORTD=0xFF;

DDRD=0x00;//3

PORTE=0x00;

DDRE=0xFF;//out USART and MIDI CHANNEL LED 

PORTF=0xFF;

DDRF=0x00;//4

PORTG=0xFF;

DDRG=0x00;//in control

PORTH=0xFF;

DDRH=0x00;//5

PORTJ=0xFF;

DDRJ=0x00;//6

PORTK=0xFF;

DDRK=0x00;//7

PORTL=0x00;

DDRL=0xFF;//out LEDS

cli();

uart_init();

sei();

// Send the test string

for (cnt = 0; cnt < strlen(test_string); cnt++) {

uart_putchar(test_string[cnt]);

}

// Check if we have received the string we sent

cnt = 0;

do

{

pra=PINA;

rta=pra^sta;

for (int i = 0; i < 8; i++)

if (rta&(1<<i))

{

if (sta&(1<<i))

{

noteon(0+i);

}

else

{

noteoff(0+i);

}

sta=pra;

}

//handlerTXUSART();

} while (1);

}

Проект симуляции в протеусе и результат работы отправки миди команд на терминале по нажатию-отжатию каждой клавиши


2019-07-20 101236 @ Kingdom

Следите за новостями))

5 ▲
24 August 2019 15:33
Kingdom

Comments

Молодец. Так получается всего 8 клавиш при замыкании на землю. А матрицей с замыканием друг на друга 8х8 было бы 64? В детских синтезаторах как раз матрица.
Этот вариант неполифонический.

Мой алгоритм позволяет запилить на этом чипе до 64-х клавиш с полной полифонией
Да, уже понятно. Так тратятся пины, но зато хоть все сразу клавиши нажимай.
Если делать через регистры - тогда выходит дорого, но зато хоть 128 клавиш нажимай и будет даже афтертач
Лень было просто клепать 64 кнопки в проекте, ахах))

Позже допишу полный алгоритм на 64 клавиши

cnt = 0;


do


{


pra=PINA;


rta=pra^sta;


for (int i = 0; i < 8; i++)


if (rta&(1<<i))


{


if (sta&(1<<i))


{


noteon(0+i);


}


else


{


noteoff(0+i);


}


sta=pra;


}


Вот это повторить еще 7 раз с нужными переменными
A поменять на B, C и так далее
В детском синтезаторе придется резать дорожки и паять клавиши раздельно
молодец, уважаю!
Прямая дорога на Кикстартер. :-) От желающих отбоя не будет. Продавать комплекты по сборке.
Я так и плаинрую - победить по продажам силиконовое китайское миди омномно за 70 баксов)))
Это вполне реально, если наладить производство, цены на запчасти будут гораздо ниже)
Можно даже продавать чисто процессор с проводами, как кит для желающих помастерить свои старые не миди раритетные синтезаторы, прикрутить к ним миди
Ради интереса прочитал, это пзц :D Молодец
Теперь это что-то великое
Теперь это чтото дорогое. Не с нашими нищебродскими зп покупать миди клавы
Мне чтбы купить сетап, нужно порядка 7-8 тыщ баксов. Где взять такие деньжищи при зп 300-400 баксов?
Ну как дела? Сделал?

Есть идея на этой основе. Надо будет пообщаться где-нибудь в телеге или скайпе. Думаю, можно нормально денег поднять. Раз у тебя такие навыки.
Почти уже готово, надо впаять диоды
Красавчик вообще! В тему написал.
Я так понял, что сразу две и более клавиш нельзя будет нажать? То есть можно, но на выходе имеем один сигнал?
Все наоборот. Моя клава - полифоническая
Please, sign up (it's quick!) or sign in, to post comments and do more fun stuff.