The forums are retiring and are now closed for new topics and comments. The existing content will remain online and accessible through 2020 to provide everyone the opportunity to save any relevant information. In the spring of 2021, these Community forums will be taken offline.

Search for index match in Topics


excel problem. averaging results of index match?

Hi all (again) new problem semi related to previous. (check my profile for the ones with NFL in the title) now the problem is i want to get the average score for each team in each season. my current formula only gets the first result of the index/match even if i use some of the tricks i've googled. the data is in the format of YearVisitingTeam(W/L/D)Score@HomeTeam(W/L/D)Score          ie   201249ersW41@2012PatriotsL34 i use a formula to strip "Year(Visiting/Home)Team(W/L/D)" so i' left with Score on either side of the "@" (that was a [redacted] pain) using any and all of the tricks i know i get either 0, 27 or an error of some sort. the only way i've been sorta able to do this is by getting the first home win, first home loss, first away win, first away loss BUT that's only 4 of 16 games each season and not a good representation of the average points for the team in a season. the sheet in question is AVG point - Reg Season the source data is 78 - current regular season (2012 season starts @ row 3152)

Question by furby    |  last reply


Problems with Excel formula? (semi-related to previous questions)

Hi all, i've got a problem with a formula in my excel spreadsheet that i'm using to get the scores for NFL teams 1978 - Current i have the data ok but the problem is with matching the the specific games. i've CONCATENATED the data to provide unique data points also it's in two columns (Home & Visitor) in the format of YearTeamW/L/DScore     eg. 2012TitansW35 in the VERY unlikely event (and i've check a random selection) that the team has 2 wins at home with the same score this could cause an error. here is the formula i'm using: (version ~8000zzzzz lol) (all one formula, just added a line break to make it fit) =(IF(MATCH($A$3&$B$2&"w*",Home_Team,0)=MATCH($A$3&$C$2&"l*",Visitor,0),INDEX(Visitor,MATCH($A$3&$C$2&"l*",Visitor,0)) ,IF(MATCH($A$3&$B$2&"d*",Home_Team,0)=MATCH($A$3&$C$2&"d*",Visitor,0),INDEX(Visitor,MATCH($A$3&$C$2&"d*",Visitor,0))))) Here's a link to the folder with the spreadsheet. (NFL Stuf (test).xlsx) Sheet: Past Season Summary - what is says. eventually where the formula is going. Sheet: nfl2011lines - 92   - the data (actually 1978 - 2012 but i named it before i added all the data) Sheet: TESTING - my "sandbox" so i don't [Censored] the main sheets Semi-Related Question1 Semi-Related Question2

Question by furby    |  last reply


What is the vernacular to describe an rf transmitter w/rotary knob that turns a servo/motor 1:1?

I'm barely schooled in robotics and RC.  Seems I'm searching for a needle in a haystack without the precise terminology.  I'd like to turn a knob on a remote chassis.  The knob presently turns manually from stop to stop approximately six times.  It meters L/min of air.  Low torque equivalent to about average for volume/bass/treble controls on a stereo. I'd like to be enabled to turn this knob at an indexible 1:1 ratio with a handheld remote transmitter that utilizes a likewise rotary knob.  Once the servo/stepper or other is mounted axially to the chassis mounted knob and powered by a wall transformer, the hand held remote need not be indexed to match it precisely.   1/4 ID hose attaches to the unit and a L/min flow meter is attached to the remote.  Rf would be highly desirable.  If necessary, or practical, I'd go with a wired rotary encoder/controller to accomplish the same.  I'm unable to find either option after a day of searching online.  Fully willing to cannibalize existing products as well.  It's sometimes much easier and cheaper way to go. Thanks

Question by brad.williamson.3110    |  last reply


cheap & easy way to do optical mark recognition (omr) or crude image scanning / processing?

What's a cheap & easy but reliable way to scan a crude drawing or do omr - optical mark recognition - ie read marks on paper like the forms you fill out with a #2 pencil ? I envision something like a row of 8 lights sensors spaced to match the lines on a 3x5 index card, you feed the card into guides aligning the lines with the sensors. Or get some graph paper & scissors and cut out some 3x5 cards. Perhaps this could be a crude scanner to scan simple drawngs at whatever resolution matches the spacing of the sensors (width of drawing would be limited to # of sensors, the length limited to arduino's memory/storage). You could hand-feed a 3x5 card with a drawing through it, the horizontal resolution would be the spacing of the sensors, maybe have some kind of roller to track the card being fed through so it knows to scan another line. I know there are sensors used by line-following robots, but what about a simple light sensor? Or buying a cheap camera element and hooking that up to a video input and processing the image inside arduino? Or processing input from composite video? Any thoughts?

Question by apple-o    |  last reply


Problem driving a stepper motor using the A4988 reprap driver board and an Arduino? Answered

Hi guys I am having a problem driving a stepper motor using the A4988 reprap driver board and an Arduino I have set up the wiring using an example I found online (Diagram attached: A4988 wiring) https://www.youtube.com/watch?v=5CmjB4WF5XA.. However the motor does not seem to turn. The motor I am using is from an old Hitachi printer which I took apart a while back. Printed on it is 0.9A/ph. It has six wires however I am using it as a bipolar stepper by just leaving the center tap of each winding unconnected. I have adjusted the VREF on the A4988 board to insure that the current is limited bellow the 0.9A. To do this I used the data sheet of the A4988. As I wanted to run the motor at full step mode, the A4988 data sheet specifies that the winding current could only reach 70 percent of the current limit. consequently: Current limit = 0.9 * 0.7 = 0.63A Current limit = Vref * 2, Therefor Vref = 0.63/2 = 0.315V or 315mV I have therefor set the current limit using the potentiometer on the A4988 to aprox 315mV Once the wiring was set up, I applied power and measured the Vref to confirm it is still the same and it was. Next I disconnected the Power to both the Arduino and the driver and connected in the stepper motor. I then connected the power and uploaded the following code: // defines pins numbers const int stepPin = 3; const int dirPin = 4; void setup() { // Sets the two pins as Outputs pinMode(stepPin,OUTPUT); pinMode(dirPin,OUTPUT); } void loop() { digitalWrite(dirPin,HIGH); // Enables the motor to move in a particular direction // Makes 200 pulses for making one full cycle rotation for(int x = 0; x < 200; x++) { digitalWrite(stepPin,HIGH); delayMicroseconds(500); digitalWrite(stepPin,LOW); delayMicroseconds(500); } delay(5000); // five second delay digitalWrite(dirPin,LOW); //Changes the rotations direction // Makes 400 pulses for making two full cycle rotation for(int x = 0; x < 400; x++) { digitalWrite(stepPin,HIGH); delayMicroseconds(500); digitalWrite(stepPin,LOW); delayMicroseconds(500); } delay(5000); } Nothing happened... started off with 5 volts on the power supply and ramped it up to aprox 12vs however still nothing happened. I can feel the heat sink heating up on the A4988 which means power was reaching it. I measured the voltages from the Arduino to the A4988 and the power supply to the driver and the voltages matched the input. I started shaking about the power connections to and suddenly the motor made one step, but that was it. So i thought it was a problem with the breadboard. I checked the connections on the breadboard and all where connected. To be safe i decided to use another breadbord. Again nothing happened. I checked the Aarduino using the 28byj48 and UNL203 driver and stepper that came with it and they worked fine. I confirmed the wiring sequences and layout multiple times and they all matched the tutorial I followed. My inital thinking was that the stepper motor was broken, so i disconnected it and tried running it using the power supple (5V) by connecting and disconnecting each coil in manually one by one, and it turned one step at a time, which meant that the stepper was working. Finally i decided to see if current was reaching the stepper, I therefore connected the Altimeter in series with one of the coils and it did not read any current, which meant that current was not reaching the coils. Now I am unsure what to do, or what has gone wrong. The vref still reads aprox 310 - 320 mV, this makes me assume that driver is not fried. I do have another A4988 driver however I started working on that one and now the Vref does not go above 62mV so I'm guessing that it is burnt, however the second one reads fine. I have tried using the enable button with the following code (Attached; A4988 wiring 2) however it still didnt' make in difference. The following code is what i used for when I set the enabled to low (Note that the pin numbers have been changed) int Index; void setup() { pinMode(4, OUTPUT); //Enable pinMode(2, OUTPUT); //Step pinMode(3, OUTPUT); //Direction digitalWrite(4,LOW); } void loop() { digitalWrite(3,HIGH); for(Index = 0; Index < 2000; Index++) { digitalWrite(2,HIGH); delayMicroseconds(500); digitalWrite(2,LOW); delayMicroseconds(500); } delay(1000); digitalWrite(3,LOW); for(Index = 0; Index < 2000; Index++) { digitalWrite(2,HIGH); delayMicroseconds(500); digitalWrite(2,LOW); delayMicroseconds(500); } delay(1000); } Why did the motors initially step (only one step upon each shake) when I shook the power supply leads? I am afraid to try that again as I think this is what damaged the first driver I was using. And why is there no current reaching the coils? I would really appreciate an opinion on this issue as I have no idea what to do Many thanks for you time. Adnan

Question by k1228438    |  last reply


FAQ: How Do I Search Instructables?

20080605. I exchanged a few PMs with Eric and it seems that even the Instructables staff is not sure about what's going on with the search feature. So ... until they can get this all straightened out, Eric recommends that we use the "site:www.instructables.com" option on Google for advanced searches. The Lucene search should work for most simple searches.. From Google's Web Search Help Center: "You can use Google to search only within one specific website by entering the search terms you're looking for, followed by the word "site" and a colon followed by the domain name. For example, here's how you'd find admission information on the Stanford University site: admission site:www.stanford.edu. Eg, "NachoMahma site:www.instructables.com" will search for my username on this site.. Try Kiteman +Law site:www.instructables.com.. . Sorry for any confusion I may have caused. . Instructables uses the Lucene search engine. I'm still trying to figure a lot of this out (can't seem to get +/- to work right, for one). As I gain insights into what is going on, I will share them here.. This is a Work In Progress and may probably contains many errors. Use at your own risk, but I can't imagine any of this causing any harm - the worst it should do is generate an error message.. Some Lucene features may not work at Instructables - I'll erase those as I become aware of them.. If you know of any search tricks or tips, or can provide any insight as to how all this works with Instructables, please PM me (or leave a comment). I'm open to all suggestions.. The following is from Lucene Query Parser Syntax (copyright 2006 by The Apache Software Foundation. Distributed under Apache License, Version 2.0). About all I've done, so far (2008-06-01), is format it for Instructables. Any info I've added is noted in the text.. Note: I can't figure out how to escape a carat (formatting code for superscript), so I've substituted "/\" (slash + back-slash), except in the pre-formatted examples.Table Of ContentsOverviewTermsFieldsTerm Modifiers (Wildcard Searches, Fuzzy Searches, Proximity Searches, Range Searches, Boosting a Term)Boolean Operators (AND, +, NOT, -)Grouping (AKA parentheses - nacho)Field GroupingEscaping Special CharactersTerms. A query is broken up into terms and operators. There are two types of terms: Single Terms and Phrases.. A Single Term is a single word such as "test" or "hello".. A Phrase is a group of words surrounded by double quotes such as "hello dolly".Multiple terms can be combined together with Boolean operators to form a more complex query (see below).Fields. Lucene supports fielded data. When performing a search you can either specify a field, or use the default field. The field names and default field is implementation specific.. You can search any field by typing the field name followed by a colon ":" and then the term you are looking for.. As an example, let's assume a Lucene index contains two fields, title and text and text is the default field. If you want to find the document entitled "The Right Way" which contains the text "don't go this way", you can enter:title:"The Right Way" AND text:goortitle:"Do it right" AND right. Since text is the default field, the field indicator is not required.. Note: The field is only valid for the term that it directly precedes, so the querytitle:Do it rightwill only find "Do" in the title field. It will find "it" and "right" in the default field (in this case the text field).Need to get a list of fields used on Instructables. - nachoWildcard Searches. Lucene supports single and multiple character wildcard searches within single terms (not within phrase queries).. To perform a single character wildcard search use the "?" symbol.. To perform a multiple character wildcard search use the "*" symbol.. The single character wildcard search looks for terms that match that with the single character replaced. For example, to search for "text" or "test" you can use the search:te?t. Multiple character wildcard searches looks for 0 or more characters. For example, to search for test, tests or tester, you can use the search:test*. You can also use the wildcard searches in the middle of a term.te*t. Note: You cannot use a * or ? symbol as the first character of a search.? and * work just like DOS wildcards, except you cannot use them as the first character - nachoFuzzy Searches. Lucene supports fuzzy searches based on the Levenshtein Distance, or Edit Distance algorithm. To do a fuzzy search use the tilde, "~", symbol at the end of a Single word Term. For example to search for a term similar in spelling to "roam" use the fuzzy search:roam~. This search will find terms like foam and roams.. Starting with Lucene 1.9 an additional (optional) parameter can specify the required similarity. The value is between 0 and 1, with a value closer to 1 only terms with a higher similarity will be matched. For example:roam~0.8. The default that is used if the parameter is not given is 0.5.Proximity Searches. Lucene supports finding words are a within a specific distance away. To do a proximity search use the tilde, "~", symbol at the end of a Phrase. For example to search for a "apache" and "jakarta" within 10 words of each other in a document use the search:"jakarta apache"~10Range Searches. Range Queries allow one to match documents whose field(s) values are between the lower and upper bound specified by the Range Query. Range Queries can be inclusive or exclusive of the upper and lower bounds. Sorting is done lexicographically.mod_date:[20020101 TO 20030101]. This will find documents whose mod_date fields have values between 20020101 and 20030101, inclusive. Note that Range Queries are not reserved for date fields. You could also use range queries with non-date fields:title:{Aida TO Carmen}. This will find all documents whose titles are between Aida and Carmen, but not including Aida and Carmen.. Inclusive range queries are denoted by square brackets. Exclusive range queries are denoted by curly brackets.Boosting a Term. Lucene provides the relevance level of matching documents based on the terms found. To boost a term use the caret, "/\", symbol with a boost factor (a number) at the end of the term you are searching. The higher the boost factor, the more relevant the term will be.. Boosting allows you to control the relevance of a document by boosting its term. For example, if you are searching forjakarta apacheand you want the term "jakarta" to be more relevant boost it using the /\ symbol along with the boost factor next to the term. You would type:jakarta^4 apache. This will make documents with the term jakarta appear more relevant. You can also boost Phrase Terms as in the example:"jakarta apache"^4 "Apache Lucene". By default, the boost factor is 1. Although the boost factor must be positive, it can be less than 1 (e.g. 0.2)Boolean Operators. Boolean operators allow terms to be combined through logic operators. Lucene supports AND, "+", OR, NOT and "-" as Boolean operators(Note: Boolean operators must be ALL CAPS).The OR operator is the default conjunction operator. This means that if there is no Boolean operator between two terms, the OR operator is used. The OR operator links two terms and finds a matching document if either of the terms exist in a document. This is equivalent to a union using sets. The symbol || can be used in place of the word OR.. To search for documents that contain either "jakarta apache" or just "jakarta" use the query:"jakarta apache" jakartaor"jakarta apache" OR jakartaAND. The AND operator matches documents where both terms exist anywhere in the text of a single document. This is equivalent to an intersection using sets. The symbol && can be used in place of the word AND.. To search for documents that contain "jakarta apache" and "Apache Lucene" use the query:"jakarta apache" AND "Apache Lucene"+. The "+" or required operator requires that the term after the "+" symbol exist somewhere in a the field of a single document.. To search for documents that must contain "jakarta" and may contain "lucene" use the query:+jakarta luceneNOT. The NOT operator excludes documents that contain the term after NOT. This is equivalent to a difference using sets. The symbol ! can be used in place of the word NOT.. To search for documents that contain "jakarta apache" but not "Apache Lucene" use the query:"jakarta apache" NOT "Apache Lucene". Note: The NOT operator cannot be used with just one term. For example, the following search will return no results:NOT "jakarta apache"-. The "-" or prohibit operator excludes documents that contain the term after the "-" symbol.. To search for documents that contain "jakarta apache" but not "Apache Lucene" use the query:"jakarta apache" -"Apache Lucene"Can anyone compare/contrast AND/+ and NOT/-? - nachoGrouping. Lucene supports using parentheses to group clauses to form sub queries. This can be very useful if you want to control the boolean logic for a query.. To search for either "jakarta" or "apache" and "website" use the query:(jakarta OR apache) AND website. This eliminates any confusion and makes sure you that website must exist and either term jakarta or apache may exist.Field Grouping. Lucene supports using parentheses to group multiple clauses to a single field.. To search for a title that contains both the word "return" and the phrase "pink panther" use the query:title:(+return +"pink panther")Escaping Special Characters. Lucene supports escaping special characters that are part of the query syntax. The current list special characters are+ - && || ! ( ) { } [] /\ " ~ * ? : \. To escape these character use the \ before the character. For example to search for (1+1):2 use the query:\(1\+1\)\:2. That's it. All corrections and/or clarifications are welcomed.

Topic by NachoMahma  


: Arduino + Adafruit wave sheild + IR + Keypad sound board

Hi , was wondering if you could point me in the right direction I'm very new to Arduino I built last year a simple board with adafruit wave shield and added a simple 12 digit key pad to play 12 sounds + power up I have got the codes for the KEYES IR receiver so know the IR is correctly connected and library loaded im trying to integrate the IR code so can change the sounds by IR remote ideally with option of the buttons (if have to loose the buttons and just use remote that's fine) have copied the code below for how it works now just buttons   I found some code for Cylon Pumpkin that works great with just the remote but would also like to integrate the 12 digit keypad Thank you in advance for any help or pointers you can suggest Richard CODE FOR 12 DIGIT BUTTON PRESS /* ADAVOICE is an Arduino-based voice pitch changer plus WAV playback. Fun for Halloween costumes, comic convention getups and other shenanigans! Hardware requirements: - Arduino Uno, Duemilanove or Diecimila (not Mega or Leonardo compatible). - Adafruit Wave Shield - Speaker attached to Wave Shield output - Battery for portable use If using the voice pitch changer, you will also need: - Adafruit Microphone Breakout - 10K potentiometer for setting pitch (or hardcode in sketch) If using the WAV playback, you will also need: - SD card - Keypad, buttons or other sensor(s) for triggering sounds Software requirements: - WaveHC library for Arduino - Demo WAV files on FAT-formatted SD card This example sketch uses a 3x4 keypad for triggering sounds...but with some changes could be adapted to use several discrete buttons, Hall effect sensors, force-sensing resistors (FSRs), I2C keypads, etc. (or if you just want the voice effect, no buttons at all). Connections: - 3.3V to mic amp+, 1 leg of potentiometer and Arduino AREF pin - GND to mic amp-, opposite leg of potentiometer - Analog pin 0 to mic amp output - Analog pin 1 to center tap of potentiometer - Wave Shield output to speaker or amplifier - Matrix is wired to pins A2, A3, A4, A5 (rows) and 6, 7, 8 (columns) - Wave shield is assumed wired as in product tutorial Potentiometer sets playback pitch. Pitch adjustment does NOT work in realtime -- audio sampling requires 100% of the ADC. Pitch setting is read at startup (or reset) and after a WAV finishes playing. POINT SPEAKER AWAY FROM MIC to avoid feedback. Written by Adafruit industries, with portions adapted from the 'PiSpeakHC' sketch included with WaveHC library. */ #include #include SdReader card; // This object holds the information for the card FatVolume vol; // This holds the information for the partition on the card FatReader root; // This holds the information for the volumes root directory FatReader file; // This object represent the WAV file for a pi digit or period WaveHC wave; // This is the only wave (audio) object, -- we only play one at a time #define error(msg) error_P(PSTR(msg)) // Macro allows error messages in flash memory #define ADC_CHANNEL 0 // Microphone on Analog pin 0 // Wave shield DAC: digital pins 2, 3, 4, 5 #define DAC_CS_PORT PORTD #define DAC_CS PORTD2 #define DAC_CLK_PORT PORTD #define DAC_CLK PORTD3 #define DAC_DI_PORT PORTD #define DAC_DI PORTD4 #define DAC_LATCH_PORT PORTD #define DAC_LATCH PORTD5 uint16_t in = 0, out = 0, xf = 0, nSamples; // Audio sample counters uint8_t adc_save; // Default ADC mode // WaveHC didn't declare it's working buffers private or static, // so we can be sneaky and borrow the same RAM for audio sampling! extern uint8_t buffer1[PLAYBUFFLEN], // Audio sample LSB buffer2[PLAYBUFFLEN]; // Audio sample MSB #define XFADE 16 // Number of samples for cross-fade #define MAX_SAMPLES (PLAYBUFFLEN - XFADE) // Remaining available audio samples // Keypad information: uint8_t rows[] = { A2, A3, A4, A5 }, // Keypad rows connect to these pins cols[] = { 6, 7, 8, 9 }, // Keypad columns connect to these pins r = 0, // Current row being examined prev = 255, // Previous key reading (or 255 if none) count = 0; // Counter for button debouncing #define DEBOUNCE 10 // Number of iterations before button 'takes' // Keypad/WAV information. Number of elements here should match the // number of keypad rows times the number of columns, plus one: const char *sound[] = { "Crashing" , "Damaged", "InFlight" , "PowerUp" , // Row 1 = Darth Vader sounds "Brkdown3" , "Brkdown2" , "Brkdown" , "PowerUp" , // Row 2 = Godzilla sounds "Landing", "drain" , "Shutdown" , "PowerUp" , // Row 3 = Dug the dog sounds "Silent", "TakeOff", "Vortex" , "PowerUp" , // Row 4 = Cartoon/SFX sound "PowerUp" }; // Extra item = boot sound //////////////////////////////////// SETUP void setup() { uint8_t i; Serial.begin(9600); // The WaveHC library normally initializes the DAC pins...but only after // an SD card is detected and a valid file is passed. Need to init the // pins manually here so that voice FX works even without a card. pinMode(2, OUTPUT); // Chip select pinMode(3, OUTPUT); // Serial clock pinMode(4, OUTPUT); // Serial data pinMode(5, OUTPUT); // Latch digitalWrite(2, HIGH); // Set chip select high // Init SD library, show root directory. Note that errors are displayed // but NOT regarded as fatal -- the program will continue with voice FX! if(!card.init()) SerialPrint_P("Card init. failed!"); else if(!vol.init(card)) SerialPrint_P("No partition!"); else if(!root.openRoot(vol)) SerialPrint_P("Couldn't open dir"); else { PgmPrintln("Files found:"); root.ls(); // Play startup sound (last file in array). playfile(sizeof(sound) / sizeof(sound[0]) - 1); } // Optional, but may make sampling and playback a little smoother: // Disable Timer0 interrupt. This means delay(), millis() etc. won't // work. Comment this out if you really, really need those functions. TIMSK0 = 0; // Set up Analog-to-Digital converter: analogReference(EXTERNAL); // 3.3V to AREF adc_save = ADCSRA; // Save ADC setting for restore later // Set keypad rows to outputs, set to HIGH logic level: for(i=0; i pinMode(rows[i], OUTPUT); digitalWrite(rows[i], HIGH); } // Set keypad columns to inputs, enable pull-up resistors: for(i=0; i pinMode(cols[i], INPUT); digitalWrite(cols[i], HIGH); } while(wave.isplaying); // Wait for startup sound to finish... startPitchShift(); // and start the pitch-shift mode by default. } //////////////////////////////////// LOOP // As written here, the loop function scans a keypad to triggers sounds // (stopping and restarting the voice effect as needed). If all you need // is a couple of buttons, it may be easier to tear this out and start // over with some simple digitalRead() calls. void loop() { uint8_t c, button; // Set current row to LOW logic state... digitalWrite(rows[r], LOW); // ...then examine column buttons for a match... for(c=0; c if(digitalRead(cols[c]) == LOW) { // First match. button = r * sizeof(cols) + c; // Get button index. if(button == prev) { // Same button as before? if(++count >= DEBOUNCE) { // Yes. Held beyond debounce threshold? if(wave.isplaying) wave.stop(); // Stop current WAV (if any) else stopPitchShift(); // or stop voice effect playfile(button); // and play new sound. while(digitalRead(cols[c]) == LOW); // Wait for button release. prev = 255; // Reset debounce values. count = 0; } } else { // Not same button as prior pass. prev = button; // Record new button and count = 0; // restart debounce counter. } } } // Restore current row to HIGH logic state and advance row counter... digitalWrite(rows[r], HIGH); if(++r >= sizeof(rows)) { // If last row scanned... r = 0; // Reset row counter // If no new sounds have been triggered at this point, and if the // pitch-shifter is not running, re-start it... if(!wave.isplaying && !(TIMSK2 & _BV(TOIE2))) startPitchShift(); } } //////////////////////////////////// HELPERS // Open and start playing a WAV file void playfile(int idx) { char filename[13]; (void)sprintf(filename,"%s.wav", sound[idx]); Serial.print("File: "); Serial.println(filename); if(!file.open(root, filename)) { PgmPrint("Couldn't open file "); Serial.print(filename); return; } if(!wave.create(file)) { PgmPrintln("Not a valid WAV"); return; } wave.play(); } //////////////////////////////////// PITCH-SHIFT CODE void startPitchShift() { // Read analog pitch setting before starting audio sampling: int pitch = analogRead(1); Serial.print("Pitch: "); Serial.println(pitch); // Right now the sketch just uses a fixed sound buffer length of // 128 samples. It may be the case that the buffer length should // vary with pitch for better results...further experimentation // is required here. nSamples = 128; //nSamples = F_CPU / 3200 / OCR2A; // ??? //if(nSamples > MAX_SAMPLES) nSamples = MAX_SAMPLES; //else if(nSamples < (XFADE * 2)) nSamples = XFADE * 2; memset(buffer1, 0, nSamples + XFADE); // Clear sample buffers memset(buffer2, 2, nSamples + XFADE); // (set all samples to 512) // WaveHC library already defines a Timer1 interrupt handler. Since we // want to use the stock library and not require a special fork, Timer2 // is used for a sample-playing interrupt here. As it's only an 8-bit // timer, a sizeable prescaler is used (32:1) to generate intervals // spanning the desired range (~4.8 KHz to ~19 KHz, or +/- 1 octave // from the sampling frequency). This does limit the available number // of speed 'steps' in between (about 79 total), but seems enough. TCCR2A = _BV(WGM21) | _BV(WGM20); // Mode 7 (fast PWM), OC2 disconnected TCCR2B = _BV(WGM22) | _BV(CS21) | _BV(CS20); // 32:1 prescale OCR2A = map(pitch, 0, 1023, F_CPU / 32 / (9615 / 2), // Lowest pitch = -1 octave F_CPU / 32 / (9615 * 2)); // Highest pitch = +1 octave // Start up ADC in free-run mode for audio sampling: DIDR0 |= _BV(ADC0D); // Disable digital input buffer on ADC0 ADMUX = ADC_CHANNEL; // Channel sel, right-adj, AREF to 3.3V regulator ADCSRB = 0; // Free-run mode ADCSRA = _BV(ADEN) | // Enable ADC _BV(ADSC) | // Start conversions _BV(ADATE) | // Auto-trigger enable _BV(ADIE) | // Interrupt enable _BV(ADPS2) | // 128:1 prescale... _BV(ADPS1) | // ...yields 125 KHz ADC clock... _BV(ADPS0); // ...13 cycles/conversion = ~9615 Hz TIMSK2 |= _BV(TOIE2); // Enable Timer2 overflow interrupt sei(); // Enable interrupts } void stopPitchShift() { ADCSRA = adc_save; // Disable ADC interrupt and allow normal use TIMSK2 = 0; // Disable Timer2 Interrupt } ISR(ADC_vect, ISR_BLOCK) { // ADC conversion complete // Save old sample from 'in' position to xfade buffer: buffer1[nSamples + xf] = buffer1[in]; buffer2[nSamples + xf] = buffer2[in]; if(++xf >= XFADE) xf = 0; // Store new value in sample buffers: buffer1[in] = ADCL; // MUST read ADCL first! buffer2[in] = ADCH; if(++in >= nSamples) in = 0; } ISR(TIMER2_OVF_vect) { // Playback interrupt uint16_t s; uint8_t w, inv, hi, lo, bit; int o2, i2, pos; // Cross fade around circular buffer 'seam'. if((o2 = (int)out) == (i2 = (int)in)) { // Sample positions coincide. Use cross-fade buffer data directly. pos = nSamples + xf; hi = (buffer2[pos] << 2) | (buffer1[pos] >> 6); // Expand 10-bit data lo = (buffer1[pos] << 2) | buffer2[pos]; // to 12 bits } if((o2 < i2) && (o2 > (i2 - XFADE))) { // Output sample is close to end of input samples. Cross-fade to // avoid click. The shift operations here assume that XFADE is 16; // will need adjustment if that changes. w = in - out; // Weight of sample (1-n) inv = XFADE - w; // Weight of xfade pos = nSamples + ((inv + xf) % XFADE); s = ((buffer2[out] << 8) | buffer1[out]) * w + ((buffer2[pos] << 8) | buffer1[pos]) * inv; hi = s >> 10; // Shift 14 bit result lo = s >> 2; // down to 12 bits } else if (o2 > (i2 + nSamples - XFADE)) { // More cross-fade condition w = in + nSamples - out; inv = XFADE - w; pos = nSamples + ((inv + xf) % XFADE); s = ((buffer2[out] << 8) | buffer1[out]) * w + ((buffer2[pos] << 8) | buffer1[pos]) * inv; hi = s >> 10; // Shift 14 bit result lo = s >> 2; // down to 12 bits } else { // Input and output counters don't coincide -- just use sample directly. hi = (buffer2[out] << 2) | (buffer1[out] >> 6); // Expand 10-bit data lo = (buffer1[out] << 2) | buffer2[out]; // to 12 bits } // Might be possible to tweak 'hi' and 'lo' at this point to achieve // different voice modulations -- robot effect, etc.? DAC_CS_PORT &= ~_BV(DAC_CS); // Select DAC // Clock out 4 bits DAC config (not in loop because it's constant) DAC_DI_PORT &= ~_BV(DAC_DI); // 0 = Select DAC A, unbuffered DAC_CLK_PORT |= _BV(DAC_CLK); DAC_CLK_PORT &= ~_BV(DAC_CLK); DAC_CLK_PORT |= _BV(DAC_CLK); DAC_CLK_PORT &= ~_BV(DAC_CLK); DAC_DI_PORT |= _BV(DAC_DI); // 1X gain, enable = 1 DAC_CLK_PORT |= _BV(DAC_CLK); DAC_CLK_PORT &= ~_BV(DAC_CLK); DAC_CLK_PORT |= _BV(DAC_CLK); DAC_CLK_PORT &= ~_BV(DAC_CLK); for(bit=0x08; bit; bit>>=1) { // Clock out first 4 bits of data if(hi & bit) DAC_DI_PORT |= _BV(DAC_DI); else DAC_DI_PORT &= ~_BV(DAC_DI); DAC_CLK_PORT |= _BV(DAC_CLK); DAC_CLK_PORT &= ~_BV(DAC_CLK); } for(bit=0x80; bit; bit>>=1) { // Clock out last 8 bits of data if(lo & bit) DAC_DI_PORT |= _BV(DAC_DI); else DAC_DI_PORT &= ~_BV(DAC_DI); DAC_CLK_PORT |= _BV(DAC_CLK); DAC_CLK_PORT &= ~_BV(DAC_CLK); } DAC_CS_PORT |= _BV(DAC_CS); // Unselect DAC if(++out >= nSamples) out = 0; } CODE I FOUND FOR IR  ClyonPumpkin That I want to integrate in above   /* * Text-to-speech example to speak the first n digits of pi. * The number is stored in flash, each digit is spoken one at a time. */ #include #include #include SdReader card;    // This object holds the information for the card FatVolume vol;    // This holds the information for the partition on the card FatReader root;   // This holds the information for the volumes root directory FatReader file;   // This object represent the WAV file for a pi digit or period WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time char eyesound[13]="eye2.wav"; int mute = 0; /* * Define macro to put error messages in flash memory */ #define error(msg) error_P(PSTR(msg)) // IR Remote code int RECV_PIN = 9;  // pin 11 used by SD card interface so select pin 9 for IR IRrecv irrecv(RECV_PIN); decode_results results; long lasttime=0, lastcode=0, timediff=0; //////////////////////////////////// SETUP void setup() {   // set up Serial library at 9600 bps   Serial.begin(9600);               if (!card.init()) {     error("Card init. failed!");   }   if (!vol.init(card)) {     error("No partition!");   }   if (!root.openRoot(vol)) {     error("Couldn't open dir");   }   irrecv.enableIRIn(); // Start the IR receiver } /////////////////////////////////// LOOP void loop() {   if(mute == 0) playcomplete(eyesound);   // check for keypress happened   if (irrecv.decode(&results;)) {      Serial.println(results.value, HEX);      switch (results.value) {        case 0x83228B74:    // 1          playcomplete("command.wav");          break;        case 0x83228F70:    // 2          playcomplete("entertan.wav");          break;        case 0x8322906F:    // 3          playcomplete("extermin.wav");          break;        case 0x83228A75:    // 4          playcomplete("leader.wav");          break;        case 0x8322847B:    // 5          playcomplete("survivor.wav");          break;         case 0x83227887:    // 6          playcomplete("atention.wav");          break;        case 0x8322629D:    // vol up          mute = 0;         // mute off          break;         case 0x83226E91:    // mute          { Serial.println("mute detected");            timediff=millis()-lasttime;            Serial.println(timediff);            if(lastcode!=results.value || (lastcode==results.value && (timediff>1600)) ) {               if( mute == 0 ) { // is mute off?                  Serial.println("toggle off to on");                  mute = 1;      // turn on                  // delay(1000);    // wait a bit for debounce                  break;                 }               if( mute == 1 ) { // is mute on?                  mute = 0;      // turn off                  Serial.println("toggle on to off");                  break;                 }              } // end if             break;           } // end case        } // end switch      lastcode = results.value;      lasttime = millis();      irrecv.resume();   // Receive the next value   } } /////////////////////////////////// HELPERS /* * print error message and halt */ void error_P(const char *str) {   PgmPrint("Error: ");   SerialPrint_P(str);   sdErrorCheck();   while(1); } /* * print error message and halt if SD I/O error */ void sdErrorCheck(void) {   if (!card.errorCode()) return;   PgmPrint("\r\nSD I/O error: ");   Serial.print(card.errorCode(), HEX);   PgmPrint(", ");   Serial.println(card.errorData(), HEX);   while(1); } /* * Play a file and wait for it to complete */ void playcomplete(char *name) {   playfile(name);   while (wave.isplaying);     // see if an error occurred while playing   sdErrorCheck(); } /* * Open and start playing a WAV file */ void playfile(char *name) {   if (wave.isplaying) {// already playing something, so stop it!     wave.stop(); // stop it   }   if (!file.open(root, name)) {     PgmPrintln("Couldn't open file ");     Serial.print(name);     return;   }   if (!wave.create(file)) {     PgmPrintln("Not a valid WAV");     return;   }   // ok time to play!   wave.play(); }

Topic by SithLordIII