Arduino kodlarını pic için uyarlama?

Başlatan metaltrrocker, 31 Ekim 2013, 15:35:18

metaltrrocker

Arkadaşlar merhaba.İnternette gördüğüm bir projeyi kendi kullanımım için pic'e uyumlu hale getirmem gerekiyor.Pic bilgim çok iyi değil bir iki şey danışmek istiyorum.
Yapmak istediğim şey ise normal oyuncak sayılabilecek orgların tuşlarını kullanıp, arabirim olarak da pic' i kullanıp bir midi klavye yapma(midi to usb kablosunu hazır alacağım).Piyasada satılanların fiyatları beni aştığı için böyle bir proje yapmak istedim.Benim için engel olan tek şey arduinodaki bazı kodları anlayamadım.Tuş taraması, tanımlamalar , dallanmaları halletmek kolay.Ama son satırlartaki "serialwrite"  kısımlarını anlayamadım.Yardımcı olabilirmisiniz?
Proje linki => http://www.codetinkerhack.com/2012/11/how-to-turn-piano-toy-into-midi.html

Arduino için kodlar.
// Pin Definitions
// Rows are connected to
const int row1 = 5;
const int row2 = 6;
const int row3 = 7;
const int row4 = 8;
 
// The 74HC595 uses a serial communication 
// link which has three pins
const int clock = 9;
const int latch = 10;
const int data = 11;
 
 
uint8_t keyToMidiMap[32];
 
boolean keyPressed[32];
 
int noteVelocity = 127;
 
 
// use prepared bit vectors instead of shifting bit left everytime
int bits[] = { B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000 };
 
 
// 74HC595 shift to next column
void scanColumn(int value) {
	digitalWrite(latch, LOW); //Pulls the chips latch low
	shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
	digitalWrite(latch, HIGH); //Pulls the latch high displaying the data
}
 
void setup() {
	
	// Map scan matrix buttons/keys to actual Midi note number. Lowest num 41 corresponds to F MIDI note.
	keyToMidiMap[0] = 48;
	keyToMidiMap[1] = 41;
	keyToMidiMap[2] = 42;
	keyToMidiMap[3] = 43;
	keyToMidiMap[4] = 44;
	keyToMidiMap[5] = 45;
	keyToMidiMap[6] = 46;
	keyToMidiMap[7] = 47;
 
	keyToMidiMap[8] = 56;
	keyToMidiMap[1 + 8] = 49;
	keyToMidiMap[2 + 8] = 50;
	keyToMidiMap[3 + 8] = 51;
	keyToMidiMap[4 + 8] = 52;
	keyToMidiMap[5 + 8] = 53;
	keyToMidiMap[6 + 8] = 54;
	keyToMidiMap[7 + 8] = 55;
 
	keyToMidiMap[16] = 64;
	keyToMidiMap[1 + 16] = 57;
	keyToMidiMap[2 + 16] = 58;
	keyToMidiMap[3 + 16] = 59;
	keyToMidiMap[4 + 16] = 60;
	keyToMidiMap[5 + 16] = 61;
	keyToMidiMap[6 + 16] = 62;
	keyToMidiMap[7 + 16] = 63;
 
	keyToMidiMap[24] = 72;
	keyToMidiMap[1 + 24] = 65;
	keyToMidiMap[2 + 24] = 66;
	keyToMidiMap[3 + 24] = 67;
	keyToMidiMap[4 + 24] = 68;
	keyToMidiMap[5 + 24] = 69;
	keyToMidiMap[6 + 24] = 70;
	keyToMidiMap[7 + 24] = 71;
 
	// setup pins output/input mode
	pinMode(data, OUTPUT);
	pinMode(clock, OUTPUT);
	pinMode(latch, OUTPUT);
 
	pinMode(row1, INPUT);
	pinMode(row2, INPUT);
	pinMode(row3, INPUT);
	pinMode(row4, INPUT);
 
    Serial.begin(31250);
 
	delay(1000);
 
}
 
void loop() {
 
	for (int col = 0; col < 8; col++) {
		
		// shift scan matrix to following column
		scanColumn(bits[col]);
 
		// check if any keys were pressed - rows will have HIGH output in this case corresponding
		int groupValue1 = digitalRead(row1);
		int groupValue2 = digitalRead(row2);
		int groupValue3 = digitalRead(row3);
		int groupValue4 = digitalRead(row4);
 
		// process if any combination of keys pressed
		if (groupValue1 != 0 || groupValue2 != 0 || groupValue3 != 0
				|| groupValue4 != 0) {
 
			if (groupValue1 != 0 && !keyPressed[col]) {
				keyPressed[col] = true;
				noteOn(0x91, keyToMidiMap[col], noteVelocity);
			}
 
			if (groupValue2 != 0 && !keyPressed[col + 8]) {
				keyPressed[col + 8] = true;
				noteOn(0x91, keyToMidiMap[col + 8], noteVelocity);
			}
 
			if (groupValue3 != 0 && !keyPressed[col + 16]) {
				keyPressed[col + 16] = true;
				noteOn(0x91, keyToMidiMap[col + 16], noteVelocity);
			}
 
			if (groupValue4 != 0 && !keyPressed[col + 24]) {
				keyPressed[col + 24] = true;
				noteOn(0x91, keyToMidiMap[col + 24], noteVelocity);
			}
 
		}
 
		//  process if any combination of keys released
		if (groupValue1 == 0 && keyPressed[col]) {
			keyPressed[col] = false;
			noteOn(0x91, keyToMidiMap[col], 0);
		}
 
		if (groupValue2 == 0 && keyPressed[col + 8]) {
			keyPressed[col + 8] = false;
			noteOn(0x91, keyToMidiMap[col + 8], 0);
		}
 
		if (groupValue3 == 0 && keyPressed[col + 16]) {
			keyPressed[col + 16] = false;
			noteOn(0x91, keyToMidiMap[col + 16], 0);
		}
 
		if (groupValue4 == 0 && keyPressed[col + 24]) {
			keyPressed[col + 24] = false;
			noteOn(0x91, keyToMidiMap[col + 24], 0);
		}
 
	}
 
}
 
 
void noteOn(int cmd, int pitch, int velocity) {
  	Serial.write(cmd);
	Serial.write(pitch);
	Serial.write(velocity);
}

not: derleyici olarak xc8 kullanacağım. pic olarak elimde ne var bakmadım ama büyük ihtimal 16f877 kullanırım.

polleme

SerialWrite komutu ile elde edilen MIDI bilgileri MIDI out portuna yazılıyor. MIDI out olarak Arduino'nun seri portu kullanılmış. Siz PIC kullanırken seri porta veri yazan komutları kullanacaksınız.

metaltrrocker

Anladım hocam teşekkürler onu bi araştırayım.
birde bu kısımda
    digitalWrite(latch, LOW); //Pulls the chips latch low
    shiftOut(data, clock, MSBFIRST, value); //Shifts out the 8 bits to the shift register
    digitalWrite(latch, HIGH); //Pulls the latch high displaying the data

"digitalwrite" onladığım kadarıyla arduinoda tanımlanan portu logic high veya low yapıyor.Peki Shiftout komutu ne işe yarıyor tam olarak?

polleme

Devrede 74HC595 kullanılmış. Shiftout komutu, eldeki verinin 595 shift registere yazılması içindir. (kaydırmalı olarak bit bit yazma için) 74HC595, bildiğiniz gibi bir sihft registerdır, 8 bittir ve çıkışlarına yazılacak 8 bitlik veri bit bit her saat sinyalinde kayacak şekilde yazılır ve 8 saat darbesinden sonra aktif edildiğinde yazılan 8 bitlik veri shift register çıkışında görünür.

metaltrrocker

Anladım hocam 595 kullanımına biraz bakmam gerekiyor.Arduino da hazır fonksiyon olarak kullanılıyor shiftot komutuyla doğru anladıysam.

polleme

Aynen öyle. Arduino hayatı çok kolaylaştırıyor ama böyle hazır komutları ezberlemeye itiyor insanı.

metaltrrocker

#6
Hazırını yapmak istemedim açıkçası.Elimde pic programlayıcı,picler,mplubx varken ögrenmeye çalışmak en iyisi:D
şu an çok baset bir yerde takıldım.
PORTBbits.RB1=1 dediğimde tamam.
ancak;
#define enable PORTBbits.RB1; şeklinde tanımlayıp
fonsiyonun içinde enable=1;
yazınca hata veriyor.

mesaj birleştirme:: 31 Ekim 2013, 16:57:08

----------------
Bu kısmı şimdilik atlıyorum tek tek portları yazarak kullandım.
Peki hocam bu Arduinodaki Serial.begin();
fonksiyonun pic deki karşılığı nedir.Usart gibi geldi bana ama bu kısımda tıkandım.

polleme

CCS C'de rs232 (baud=9600,xmit=PIN_C6, rcv=PIN_C7, parity=N, stop=1)

MikroC veya diğer dillerdekini şu anda hatırlayamadım. Temel olarak parametrelerini verip seri portu aktif etmeye yarayan komuttur.

metaltrrocker

Bir de hocam çok basit bir şey soracamBu arduino kadlarında main() fonskiyonunu göremedim?

polleme

Arduino programlamada main() yoktur, yerine loop fonksiyonu olur. setup() altında ilk ayarlarınızı yapıp loop() altında asıl programı çalıştırırsınız.

metaltrrocker

Loop fonksiyonunu while döngüsü ile birleştirip main() içerisine atsam bir sorun olmaz o zaman değilmi?

polleme

Loop içindeki kısmı while(1) ile main() içine atabilirsiniz.

metaltrrocker

#12
Aynen hocam ben de o şekilde düşündüm:)

mesaj birleştirme:: 31 Ekim 2013, 18:27:15

Hocam baya bi kafa patlatıp birşeyler yapmaya çalıştım.Biraz sonra proteus simulasyonunu deneyecem.
kodlarda sıkıntı çıkmaz umarım.
/* 
 * File:   midi.c
 * Author: Psefit
 *
 * Created on 31 Ekim 2013 Per?embe, 15:43
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
//#include "usart.h"
//#include "delay.h"
// PIC16F877A Configuration Bit Settings
// CONFIG
#pragma config FOSC = EXTRC     // Oscillator Selection bits (RC oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define row1 PORTBbits.RB3;
#define row2 PORTAbits.RA1;
#define row3 PORTAbits.RA2;
#define row4 PORTAbits.RA3;
#define clock PORTBbits.RB0;  //SH_CP clock
#define enable1 PORTBbits.RB1; //ST_CP enable
#define data  PORTBbits.RB2;  // DS   data olarak tanımlandı.
// Definitions
//#define IncomingData_LED   LATDbits.LATD4	// Incoming Data LED shows that uart data has been received
volatile unsigned int uart_data;    // use 'volatile' qualifer as this is changed in ISR
#define _XTAL_FREQ  4000000    // this is used by the __delay_ms(xx) and __delay_us(xx) functions

int noteVelocity = 127;
char keyPressed[32];
char keyToMidiMap[32];
char bits[] = { 0x01, 0x02,0x04,0x08,0x10,0x20,0x40,0x80 };

// 74HC595 shift to next column
void three_wire_control(unsigned char temp) {
    char i;
    PORTBbits.RB1=0;//enable1
    for (i = 0; i < 8; i++) {
        PORTBbits.RB0 = 0; //clock
        if ((temp << i)&0x80)
            PORTBbits.RB2= 1;
        else
            PORTBbits.RB2 = 0;
        PORTBbits.RB0 = 1;
    }
    PORTBbits.RB1 = 1;
}


void setup() {

	// Map scan matrix buttons/keys to actual Midi note number. Lowest num 41 corresponds to F MIDI note.
	keyToMidiMap[0] = 48;
	keyToMidiMap[1] = 41;
	keyToMidiMap[2] = 42;
	keyToMidiMap[3] = 43;
	keyToMidiMap[4] = 44;
	keyToMidiMap[5] = 45;
	keyToMidiMap[6] = 46;
	keyToMidiMap[7] = 47;

	keyToMidiMap[8] = 56;
	keyToMidiMap[1 + 8] = 49;
	keyToMidiMap[2 + 8] = 50;
	keyToMidiMap[3 + 8] = 51;
	keyToMidiMap[4 + 8] = 52;
	keyToMidiMap[5 + 8] = 53;
	keyToMidiMap[6 + 8] = 54;
	keyToMidiMap[7 + 8] = 55;

	keyToMidiMap[16] = 64;
	keyToMidiMap[1 + 16] = 57;
	keyToMidiMap[2 + 16] = 58;
	keyToMidiMap[3 + 16] = 59;
	keyToMidiMap[4 + 16] = 60;
	keyToMidiMap[5 + 16] = 61;
	keyToMidiMap[6 + 16] = 62;
	keyToMidiMap[7 + 16] = 63;

	keyToMidiMap[24] = 72;
	keyToMidiMap[1 + 24] = 65;
	keyToMidiMap[2 + 24] = 66;
	keyToMidiMap[3 + 24] = 67;
	keyToMidiMap[4 + 24] = 68;
	keyToMidiMap[5 + 24] = 69;
	keyToMidiMap[6 + 24] = 70;
	keyToMidiMap[7 + 24] = 71;

	// setup pins output/input mode
        
	__delay_ms(10);

}




void interrupt ISR() {

    if (PIR1bits.RCIF)          // see if interrupt caused by incoming data
    {
        uart_data = RC1;     // read the incoming data
        PIR1bits.RCIF = 0;      // clear interrupt flag

    }

}

void uartxmit(int mydatabyte) {

    while(!TXSTAbits.TRMT);    // make sure buffer full bit is high before transmitting
    TXREG = mydatabyte;       // transmit data
}
void noteOn(int cmd, int pitch, int velocity) {

        uartxmit(cmd);
	uartxmit(pitch);
        uartxmit(velocity);
        
}


void main(void) {

     //*************************************************************************************
    // Set up the UART
    // Note: See the datasheet for tables with the values of SPBRGH:SPBRGL already
    // calculated based on different values of Fosc and BRGH and desired
    // baud rates.
    //*************************************************************************************
    

    TXSTAbits.BRGH=1;       // select low speed Baud Rate (see baud rate calcs below)
    TXSTAbits.TX9=0;        // select 8 data bits
    TXSTAbits.TXEN = 1;     // enable transmit
    TRISCbits.TRISC6 = 0; // RC6 = TX out
    
    TRISBbits.TRISB0=0;
    TRISBbits.TRISB1=0;
    TRISBbits.TRISB2=0;
    TRISBbits.TRISB3=1;
    TRISBbits.TRISB4=1;
    TRISBbits.TRISB5=1;
    TRISBbits.TRISB6=1;

    RCSTAbits.SPEN=1;       // serial port is enabled
    RCSTAbits.RX9=0;        // select 8 data bits
    RCSTAbits.CREN=1;       // receive enabled

    // calculate values of SPBRGL and SPBRGH based on the desired baud rate
    //
    // For 8 bit Async mode with BRGH=0: Desired Baud rate = Fosc/64([SPBRGH:SPBRGL]+1)
    // For 8 bit Async mode with BRGH=1: Desired Baud rate = Fosc/16([SPBRGH:SPBRGL]+1)

    // For our example,we will use BRGH=0,Fosc=16Mhz and we want baud rate=9600
    //
    //  9600 = Fosc/64([SPBRGH:SPBRGL]+1)
    //  9600 = Fosc/64(X+1)
    //  9600 = Fosc/64X + 64
    //  9600(64X + 64) = Fosc
    //  X = [Fosc/(9600)(64)]-1
    //  X = [16000000/(9600)(64)] -1
    //  X = SPBRGH:SPBRGL = 25.01 (round to 25)

    SPBRG=25;  // here is calculated value of SPBRGH and SPBRGL


    PIR1bits.RCIF=0;        // make sure receive interrupt flag is clear
    PIE1bits.RCIE=1;        // enable UART Receive interrupt
    INTCONbits.PEIE = 1;    // Enable peripheral interrupt
    INTCONbits.GIE = 1;     // enable global interrupt

    

    __delay_ms(50);        // give time for voltage levels on board to settle
    while(1) {
        for (int col = 0; col < 8; col++) {

            // shift scan matrix to following column
            three_wire_control(bits[col]);
            setup();

            // check if any keys were pressed - rows will have HIGH output in this case corresponding
            int groupValue1 = PORTBbits.RB3;
            int groupValue2 = PORTBbits.RB4;
            int groupValue3 = PORTBbits.RB5;
            int groupValue4 = PORTBbits.RB6;

            // process if any combination of keys pressed
            if (groupValue1 != 0 || groupValue2 != 0 || groupValue3 != 0
                    || groupValue4 != 0) {

                if (groupValue1 != 0 && !keyPressed[col]) {
                    keyPressed[col] = 1;
                    noteOn(0x91, keyToMidiMap[col], noteVelocity);
                }

                if (groupValue2 != 0 && !keyPressed[col + 8]) {
                    keyPressed[col + 8] = 1;
                    noteOn(0x91, keyToMidiMap[col + 8], noteVelocity);
                }

                if (groupValue3 != 0 && !keyPressed[col + 16]) {
                    keyPressed[col + 16] = 1;
                    noteOn(0x91, keyToMidiMap[col + 16], noteVelocity);
                }

                if (groupValue4 != 0 && !keyPressed[col + 24]) {
                    keyPressed[col + 24] = 1;
                    noteOn(0x91, keyToMidiMap[col + 24], noteVelocity);
                }

            }

            //  process if any combination of keys released
            if (groupValue1 == 0 && keyPressed[col]) {
                keyPressed[col] = 0;
                noteOn(0x91, keyToMidiMap[col], 0);
            }

            if (groupValue2 == 0 && keyPressed[col + 8]) {
                keyPressed[col + 8] = 0;
                noteOn(0x91, keyToMidiMap[col + 8], 0);
            }

            if (groupValue3 == 0 && keyPressed[col + 16]) {
                keyPressed[col + 16] = 0;
                noteOn(0x91, keyToMidiMap[col + 16], 0);
            }

            if (groupValue4 == 0 && keyPressed[col + 24]) {
                keyPressed[col + 24] = 0;
                noteOn(0x91, keyToMidiMap[col + 24], 0);
            }

        }

    }


}

Kodları son şekliyle düzenledim.

metaltrrocker

Simuyasyon çalışmıyor biryerde bir hata yapıyorum ama anlayamadım.Yardımcı olabilirmisiniz.
[IMG]http://img59.imageshack.us/img59/8511/73y8.jpg[/img]

mehmet

main() bloğu içinde setup() fonksiyonunu
göremedim. Hata bende mi acaba?
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr