Picproje Elektronik Sitesi

DERLEYİCİLER => Microchip MPLAB C serisi => Konuyu başlatan: metaltrrocker - 31 Ekim 2013, 15:35:18

Başlık: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 15:35:18
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 (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.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: polleme - 31 Ekim 2013, 15:52:24
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.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 15:56:07
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?
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: polleme - 31 Ekim 2013, 16:03:37
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.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 16:24:52
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.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: polleme - 31 Ekim 2013, 16:27:59
Aynen öyle. Arduino hayatı çok kolaylaştırıyor ama böyle hazır komutları ezberlemeye itiyor insanı.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 16:38:22
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.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: polleme - 31 Ekim 2013, 17:04:54
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.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 17:28:24
Bir de hocam çok basit bir şey soracamBu arduino kadlarında main() fonskiyonunu göremedim?
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: polleme - 31 Ekim 2013, 17:50:04
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.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 17:56:55
Loop fonksiyonunu while döngüsü ile birleştirip main() içerisine atsam bir sorun olmaz o zaman değilmi?
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: polleme - 31 Ekim 2013, 17:58:19
Loop içindeki kısmı while(1) ile main() içine atabilirsiniz.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 17:59:10
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.
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 22:07:38
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] (http://imageshack.us/photo/my-images/59/73y8.jpg/)
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: mehmet - 31 Ekim 2013, 22:50:57
main() bloğu içinde setup() fonksiyonunu
göremedim. Hata bende mi acaba?
Başlık: Ynt: Arduino kodlarını pic için uyarlama?
Gönderen: metaltrrocker - 31 Ekim 2013, 23:24:05
Alıntı yapılan: mehmet - 31 Ekim 2013, 22:50:57
main() bloğu içinde setup() fonksiyonunu
göremedim. Hata bende mi acaba?
Aynen hocam unutmuşum dalgınlıktan.
birde şu kısmı B portu ile değiştirmeyi unutmuşum.

        int groupValue1 = PORTAbits.RA0;
        int groupValue2 = PORTAbits.RA1;
        int groupValue3 = PORTAbits.RA2;
        int groupValue4 = PORTAbits.RA3;


mesaj birleştirme:: 31 Ekim 2013, 23:30:41

Setup () fonksiyonunu main içerisinde kulandım ancak saçma sonuçlar çıkıyor.Baud=9600 olarak ayarladım.

mesaj birleştirme:: 01 Kasım 2013, 00:06:11

Dostlar galiba başardım:) Tabi sizin de onayınızı bekliyorum.
[IMG]http://img42.imageshack.us/img42/4412/14b1.jpg[/img] (http://imageshack.us/photo/my-images/42/14b1.jpg/)